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

View file

@ -29,13 +29,13 @@ public:
void addDefinition(absl::string_view id, absl::string_view value);
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 setMaximumIncludeDepth(size_t depth) { _maxIncludeDepth = depth; }
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_map<std::string, std::string> DefinitionSet;
@ -63,7 +63,7 @@ public:
void setListener(Listener* listener) noexcept { _listener = listener; }
private:
void includeNewFile(const fs::path& path);
void includeNewFile(const fs::path& path, std::unique_ptr<Reader> reader = nullptr);
void processTopLevel();
void processDirective();
void processHeader();

View file

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

View file

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

View file

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

View file

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