Skip to content

Commit

Permalink
Fix some cases of value parsing under ARIA (fix Salamander)
Browse files Browse the repository at this point in the history
  • Loading branch information
jpcima committed May 15, 2020
1 parent a138b93 commit 4b8eaeb
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 26 deletions.
61 changes: 36 additions & 25 deletions src/sfizz/parser/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,36 +285,47 @@ void Parser::processOpcode()
std::string valueRaw;
extractToEol(reader, &valueRaw);

// if a "=" or "<" character was hit, it means we read too far
size_t position = valueRaw.find_first_of("=<");
if (position != valueRaw.npos) {
char hitChar = valueRaw[position];

// if it was "=", rewind before the opcode name and spaces preceding
if (hitChar == '=') {
while (position > 0 && isRawOpcodeNameChar(valueRaw[position - 1]))
--position;
while (position > 0 && isSpaceChar(valueRaw[position - 1]))
--position;
}

absl::string_view excess(&valueRaw[position], valueRaw.size() - position);
reader.putBackChars(excess);
valueRaw.resize(position);
size_t endPosition = 0;

for (size_t valueSize = valueRaw.size(); endPosition < valueSize;) {
size_t i = endPosition + 1;

if (isSpaceChar(valueRaw[endPosition])) {
// check if the rest of the string is to consume or not
bool stop = false;

// consume space characters following
while (i < valueSize && isSpaceChar(valueRaw[endPosition + 1]))
++i;

// if there aren't non-space characters following, do not extract
if (i == valueSize)
stop = true;
// if a "=" or "<" character is next, a header or a directive follows
else if (valueRaw[i] == '<' || valueRaw[i] == '#')
stop = true;
// if sequence of identifier chars and then "=", an opcode follows
else if (isIdentifierChar(valueRaw[i])) {
++i;
while (i < valueSize && isIdentifierChar(valueRaw[i]))
++i;
if (i < valueSize && valueRaw[i] == '=')
stop = true;
}

// ensure that we are landing back next to a space char
if (hitChar == '=' && !reader.hasOneOfChars(" \t\r\n")) {
SourceLocation end = reader.location();
emitError({ valueStart, end }, "Unexpected `=` in opcode value.");
recover();
return;
if (stop)
break;
}

endPosition = i;
}

while (!valueRaw.empty() && isSpaceChar(valueRaw.back())) {
reader.putBackChar(valueRaw.back());
valueRaw.pop_back();
if (endPosition != valueRaw.size()) {
absl::string_view excess(&valueRaw[endPosition], valueRaw.size() - endPosition);
reader.putBackChars(excess);
valueRaw.resize(endPosition);
}

SourceLocation valueEnd = reader.location();

if (!_currentHeader)
Expand Down
35 changes: 34 additions & 1 deletion tests/ParsingT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -629,10 +629,43 @@ TEST_CASE("[Parsing] Opcode value special character")
parser.setListener(&mock);
parser.parseString("/opcodeValueSpecialCharacter.sfz",
R"(<region>
sample=Alto-Flute-sus-C#4-PB-loop.wav)");
sample=Alto-Flute-sus-C#4-PB-loop.wav
<region>
sample=foo=bar<quux.wav)");

std::vector<std::vector<sfz::Opcode>> expectedMembers = {
{{"sample", "Alto-Flute-sus-C#4-PB-loop.wav"}},
{{"sample", "foo=bar<quux.wav"}},
};
std::vector<std::string> expectedHeaders = {
"region", "region"
};
std::vector<sfz::Opcode> expectedOpcodes;

for (auto& members: expectedMembers)
for (auto& opcode: members)
expectedOpcodes.push_back(opcode);

REQUIRE(mock.beginnings == 1);
REQUIRE(mock.endings == 1);
REQUIRE(mock.errors.empty());
REQUIRE(mock.warnings.empty());
REQUIRE(mock.opcodes == expectedOpcodes);
REQUIRE(mock.headers == expectedHeaders);
REQUIRE(mock.fullBlockHeaders == expectedHeaders);
REQUIRE(mock.fullBlockMembers == expectedMembers);
}

TEST_CASE("[Parsing] Opcode value with inline directives")
{
sfz::Parser parser;
ParsingMocker mock;
parser.setListener(&mock);
parser.parseString("/opcodeValueWithInlineDirective.sfz",
R"(<region>#define $VEL v1 sample=$VEL.wav #define $FOO bar)");

std::vector<std::vector<sfz::Opcode>> expectedMembers = {
{{"sample", "v1.wav"}},
};
std::vector<std::string> expectedHeaders = {
"region"
Expand Down

0 comments on commit 4b8eaeb

Please sign in to comment.