String parsing without originalDirectory setter

This commit is contained in:
Jean Pierre Cimalando 2020-03-28 01:45:59 +01:00
parent 25fa15acbe
commit ba23ed810a
6 changed files with 41 additions and 61 deletions

View file

@ -33,21 +33,23 @@ void Parser::reset()
} }
void Parser::parseFile(const fs::path& path) void Parser::parseFile(const fs::path& path)
{
parseVirtualFile(path, nullptr);
}
void Parser::parseString(const fs::path& path, absl::string_view sfzView)
{
parseVirtualFile(path, absl::make_unique<StringViewReader>(path, sfzView));
}
void Parser::parseVirtualFile(const fs::path& path, std::unique_ptr<Reader> reader)
{ {
reset(); reset();
if (_listener) if (_listener)
_listener->onParseBegin(); _listener->onParseBegin();
if (path.empty()) includeNewFile(path, std::move(reader));
return;
if (path.is_relative())
setOriginalDirectory(originalDirectory() / path);
else
setOriginalDirectory(path.parent_path());
includeNewFile(path);
processTopLevel(); processTopLevel();
flushCurrentHeader(); flushCurrentHeader();
@ -55,32 +57,14 @@ void Parser::parseFile(const fs::path& path)
_listener->onParseEnd(); _listener->onParseEnd();
} }
void Parser::parseString(absl::string_view sfzView) void Parser::includeNewFile(const fs::path& path, std::unique_ptr<Reader> reader)
{
reset();
if (_listener)
_listener->onParseBegin();
_included.push_back(absl::make_unique<StringViewReader>(sfzView));
processTopLevel();
flushCurrentHeader();
if (_listener)
_listener->onParseEnd();
}
void Parser::setOriginalDirectory(const fs::path& originalDirectory) noexcept
{
_originalDirectory = originalDirectory;
}
void Parser::includeNewFile(const fs::path& path)
{ {
fs::path fullPath = fs::path fullPath =
(path.empty() || path.is_absolute()) ? path : _originalDirectory / path; (path.empty() || path.is_absolute()) ? path : _originalDirectory / path;
if (_pathsIncluded.find(fullPath.string()) != _pathsIncluded.end()) { if (_pathsIncluded.empty())
_originalDirectory = fullPath.parent_path();
else if (_pathsIncluded.find(fullPath.string()) != _pathsIncluded.end()) {
if (_recursiveIncludeGuardEnabled) if (_recursiveIncludeGuardEnabled)
return; return;
} }
@ -92,15 +76,18 @@ void Parser::includeNewFile(const fs::path& path)
return; return;
} }
auto fileReader = absl::make_unique<FileReader>(fullPath); if (!reader) {
if (fileReader->hasError()) { auto fileReader = absl::make_unique<FileReader>(fullPath);
SourceLocation loc = fileReader->location(); if (fileReader->hasError()) {
emitError({ loc, loc }, "Cannot open file for reading: " + fullPath.string()); SourceLocation loc = fileReader->location();
return; emitError({ loc, loc }, "Cannot open file for reading: " + fullPath.string());
return;
}
reader = std::move(fileReader);
} }
_pathsIncluded.insert(fullPath.string()); _pathsIncluded.insert(fullPath.string());
_included.push_back(std::move(fileReader)); _included.push_back(std::move(reader));
} }
void Parser::processTopLevel() void Parser::processTopLevel()

View file

@ -29,13 +29,13 @@ public:
void addDefinition(absl::string_view id, absl::string_view value); void addDefinition(absl::string_view id, absl::string_view value);
void parseFile(const fs::path& path); void parseFile(const fs::path& path);
void parseString(absl::string_view sfzView); void parseString(const fs::path& path, absl::string_view sfzView);
void parseVirtualFile(const fs::path& path, std::unique_ptr<Reader> reader);
void setRecursiveIncludeGuardEnabled(bool en) { _recursiveIncludeGuardEnabled = en; } void setRecursiveIncludeGuardEnabled(bool en) { _recursiveIncludeGuardEnabled = en; }
void setMaximumIncludeDepth(size_t depth) { _maxIncludeDepth = depth; } void setMaximumIncludeDepth(size_t depth) { _maxIncludeDepth = depth; }
const fs::path& originalDirectory() const noexcept { return _originalDirectory; } const fs::path& originalDirectory() const noexcept { return _originalDirectory; }
void setOriginalDirectory(const fs::path& originalDirectory) noexcept;
typedef absl::flat_hash_set<std::string> IncludeFileSet; typedef absl::flat_hash_set<std::string> IncludeFileSet;
typedef absl::flat_hash_map<std::string, std::string> DefinitionSet; typedef absl::flat_hash_map<std::string, std::string> DefinitionSet;
@ -63,7 +63,7 @@ public:
void setListener(Listener* listener) noexcept { _listener = listener; } void setListener(Listener* listener) noexcept { _listener = listener; }
private: private:
void includeNewFile(const fs::path& path); void includeNewFile(const fs::path& path, std::unique_ptr<Reader> reader = nullptr);
void processTopLevel(); void processTopLevel();
void processDirective(); void processDirective();
void processHeader(); void processHeader();

View file

@ -139,10 +139,9 @@ int FileReader::getNextStreamByte()
return _fileStream.get(); return _fileStream.get();
} }
StringViewReader::StringViewReader(absl::string_view sfzView) StringViewReader::StringViewReader(const fs::path& filePath, absl::string_view sfzView)
: Reader({}), _sfzView(sfzView) : Reader(filePath), _sfzView(sfzView)
{ {
} }
int StringViewReader::getNextStreamByte() int StringViewReader::getNextStreamByte()

View file

@ -124,7 +124,7 @@ private:
*/ */
class StringViewReader : public Reader { class StringViewReader : public Reader {
public: public:
explicit StringViewReader(absl::string_view sfzView); explicit StringViewReader(const fs::path& filePath, absl::string_view sfzView);
protected: protected:
int getNextStreamByte() override; int getNextStreamByte() override;

View file

@ -2,7 +2,6 @@
#include "parser/Parser.h" #include "parser/Parser.h"
#include <QApplication> #include <QApplication>
#include <QTimer> #include <QTimer>
#include <QTemporaryFile>
#include <QFileInfo> #include <QFileInfo>
#include <QDir> #include <QDir>
#include <QTextBlock> #include <QTextBlock>
@ -114,14 +113,8 @@ void Application::requestParseCheck()
void Application::runParseCheck() void Application::runParseCheck()
{ {
QByteArray code = _ui.sfzEdit->toPlainText().toLatin1(); QByteArray code = _ui.sfzEdit->toPlainText().toLatin1();
QTemporaryFile temp(QDir::tempPath() + "/parseXXXXXX.sfz");
temp.open();
temp.write(code);
temp.flush();
_blockTextChanged = true; _blockTextChanged = true;
_parser.parseFile(temp.fileName().toStdString()); _parser.parseString("/virtual.sfz", absl::string_view(code.data(), code.size()));
_blockTextChanged = false; _blockTextChanged = false;
} }

View file

@ -179,7 +179,7 @@ TEST_CASE("[Parsing] Empty")
sfz::Parser parser; sfz::Parser parser;
ParsingMocker mock; ParsingMocker mock;
parser.setListener(&mock); parser.setListener(&mock);
parser.parseString(""); parser.parseString("/empty.sfz", "");
REQUIRE(mock.beginnings == 1); REQUIRE(mock.beginnings == 1);
REQUIRE(mock.endings == 1); REQUIRE(mock.endings == 1);
REQUIRE(mock.errors.empty()); REQUIRE(mock.errors.empty());
@ -201,7 +201,7 @@ TEST_CASE("[Parsing] Empty2")
sfz::Parser parser; sfz::Parser parser;
ParsingMocker mock; ParsingMocker mock;
parser.setListener(&mock); parser.setListener(&mock);
parser.parseString(emptySfz); parser.parseString("/empty2.sfz", emptySfz);
REQUIRE(mock.beginnings == 1); REQUIRE(mock.beginnings == 1);
REQUIRE(mock.endings == 1); REQUIRE(mock.endings == 1);
REQUIRE(mock.errors.empty()); REQUIRE(mock.errors.empty());
@ -224,7 +224,7 @@ TEST_CASE("[Parsing] Jpcima good region")
sfz::Parser parser; sfz::Parser parser;
ParsingMocker mock; ParsingMocker mock;
parser.setListener(&mock); parser.setListener(&mock);
parser.parseString(R"( parser.parseString("/goodRegion.sfz", R"(
<region> sample=*silence key=69 <region> sample=*silence key=69
sample=My Directory/My Wave.wav // path with spaces and a comment sample=My Directory/My Wave.wav // path with spaces and a comment
sample=My Directory/My Wave.wav key=69 // path with spaces, and other opcode following sample=My Directory/My Wave.wav key=69 // path with spaces, and other opcode following
@ -256,7 +256,7 @@ void memberTestNew(absl::string_view member, absl::string_view opcode, absl::str
sfz::Parser parser; sfz::Parser parser;
ParsingMocker mock; ParsingMocker mock;
parser.setListener(&mock); parser.setListener(&mock);
parser.parseString(absl::StrCat("<region> ", member)); parser.parseString("/memberTestNew.sfz", absl::StrCat("<region> ", member));
REQUIRE(mock.opcodes.size() == 1); REQUIRE(mock.opcodes.size() == 1);
REQUIRE(mock.headers.size() == 1); REQUIRE(mock.headers.size() == 1);
REQUIRE(mock.fullBlockHeaders.size() == 1); REQUIRE(mock.fullBlockHeaders.size() == 1);
@ -296,7 +296,7 @@ TEST_CASE("[Parsing] bad headers")
sfz::Parser parser; sfz::Parser parser;
ParsingMocker mock; ParsingMocker mock;
parser.setListener(&mock); parser.setListener(&mock);
parser.parseString( parser.parseString("/badHeaders.sfz",
R"(<> R"(<>
<ab@cd> dummy_member=no <ab@cd> dummy_member=no
)" )"
@ -317,7 +317,7 @@ void defineTestNew(const std::string& directive, const std::string& variable, co
sfz::Parser parser; sfz::Parser parser;
ParsingMocker mock; ParsingMocker mock;
parser.setListener(&mock); parser.setListener(&mock);
parser.parseString(directive); parser.parseString("/defineTestNew.sfz", directive);
const auto defines = parser.getDefines(); const auto defines = parser.getDefines();
REQUIRE(defines.contains(variable)); REQUIRE(defines.contains(variable));
REQUIRE(defines.at(variable) == value); REQUIRE(defines.at(variable) == value);
@ -342,7 +342,8 @@ TEST_CASE("[Parsing] Malformed includes")
sfz::Parser parser; sfz::Parser parser;
ParsingMocker mock; ParsingMocker mock;
parser.setListener(&mock); parser.setListener(&mock);
parser.parseString(R"(#include "MyFileWhichDoesNotExist1.sfz parser.parseString("/malformedIncludes.sfz",
R"(#include "MyFileWhichDoesNotExist1.sfz
#include MyFileWhichDoesNotExist1.sfz)"); #include MyFileWhichDoesNotExist1.sfz)");
REQUIRE(mock.errors.size() == 2); REQUIRE(mock.errors.size() == 2);
REQUIRE(mock.errors[0].start.lineNumber == 0); REQUIRE(mock.errors[0].start.lineNumber == 0);
@ -362,7 +363,7 @@ TEST_CASE("[Parsing] Headers (new parser)")
sfz::Parser parser; sfz::Parser parser;
ParsingMocker mock; ParsingMocker mock;
parser.setListener(&mock); parser.setListener(&mock);
parser.parseString("<header>param1=value1 param2=value2 <next>"); parser.parseString("/headers.sfz", "<header>param1=value1 param2=value2 <next>");
std::vector<std::vector<sfz::Opcode>> expectedMembers = { std::vector<std::vector<sfz::Opcode>> expectedMembers = {
{{"param1", "value1"}, {"param2", "value2"}}, {{"param1", "value1"}, {"param2", "value2"}},
{} {}
@ -391,7 +392,7 @@ TEST_CASE("[Parsing] Headers (new parser)")
sfz::Parser parser; sfz::Parser parser;
ParsingMocker mock; ParsingMocker mock;
parser.setListener(&mock); parser.setListener(&mock);
parser.parseString("<header>param1=value1 param2=value2"); parser.parseString("/eolHeaderMatch.sfz", "<header>param1=value1 param2=value2");
std::vector<std::vector<sfz::Opcode>> expectedMembers = { std::vector<std::vector<sfz::Opcode>> expectedMembers = {
{{"param1", "value1"}, {"param2", "value2"}} {{"param1", "value1"}, {"param2", "value2"}}
}; };