From 692b2cda6af27072ff7d58897e7c01fec527f250 Mon Sep 17 00:00:00 2001 From: Paul Fd Date: Thu, 5 Mar 2020 16:07:23 +0100 Subject: [PATCH] Silently ignore ampersands in opcode name --- src/sfizz/Opcode.cpp | 4 ++-- src/sfizz/StringViewHelpers.h | 21 +++++++++++++++++++++ tests/OpcodeT.cpp | 28 ++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/sfizz/Opcode.cpp b/src/sfizz/Opcode.cpp index 344c31e9..cc022c11 100644 --- a/src/sfizz/Opcode.cpp +++ b/src/sfizz/Opcode.cpp @@ -20,7 +20,7 @@ sfz::Opcode::Opcode(absl::string_view inputOpcode, absl::string_view inputValue) while (nextNumIndex != opcode.npos) { const auto numLetters = nextNumIndex - nextCharIndex; parameterPosition += numLetters; - lettersOnlyHash = hash(opcode.substr(nextCharIndex, numLetters), lettersOnlyHash); + lettersOnlyHash = hashNoAmpersand(opcode.substr(nextCharIndex, numLetters), lettersOnlyHash); nextCharIndex = opcode.find_first_not_of("1234567890", nextNumIndex); uint32_t returnedValue; @@ -34,5 +34,5 @@ sfz::Opcode::Opcode(absl::string_view inputOpcode, absl::string_view inputValue) } if (nextCharIndex != opcode.npos) - lettersOnlyHash = hash(opcode.substr(nextCharIndex), lettersOnlyHash); + lettersOnlyHash = hashNoAmpersand(opcode.substr(nextCharIndex), lettersOnlyHash); } diff --git a/src/sfizz/StringViewHelpers.h b/src/sfizz/StringViewHelpers.h index 0cc49d38..aeb2f2bd 100644 --- a/src/sfizz/StringViewHelpers.h +++ b/src/sfizz/StringViewHelpers.h @@ -66,3 +66,24 @@ constexpr uint64_t hash(absl::string_view s, uint64_t h = Fnv1aBasis) return h; } + +/** + * @brief Same function as `hash()` but ignores ampersands (&) + * + * See e.g. the Region.cpp file + * + * @param s the input string to be hashed + * @param h the hashing seed to use + * @return uint64_t + */ +constexpr uint64_t hashNoAmpersand(absl::string_view s, uint64_t h = Fnv1aBasis) +{ + if (s.length() > 0) { + if (s.front() == '&') + return hashNoAmpersand( { s.data() + 1, s.length() - 1 }, h ); + else + return hashNoAmpersand( { s.data() + 1, s.length() - 1 }, (h ^ s.front()) * Fnv1aPrime ); + } + + return h; +} diff --git a/tests/OpcodeT.cpp b/tests/OpcodeT.cpp index d55d7aff..ffbb07ab 100644 --- a/tests/OpcodeT.cpp +++ b/tests/OpcodeT.cpp @@ -28,6 +28,24 @@ TEST_CASE("[Opcode] Construction") REQUIRE(opcode.value == "dummy"); } + SECTION("Normal construction with ampersand") + { + sfz::Opcode opcode { "sample&_ampersand", "dummy" }; + REQUIRE(opcode.opcode == "sample&_ampersand"); + REQUIRE(opcode.lettersOnlyHash == hash("sample_ampersand")); + REQUIRE(opcode.parameters.empty()); + REQUIRE(opcode.value == "dummy"); + } + + SECTION("Normal construction with multiple ampersands") + { + sfz::Opcode opcode { "&sample&_ampersand&", "dummy" }; + REQUIRE(opcode.opcode == "&sample&_ampersand&"); + REQUIRE(opcode.lettersOnlyHash == hash("sample_ampersand")); + REQUIRE(opcode.parameters.empty()); + REQUIRE(opcode.value == "dummy"); + } + SECTION("Parameterized opcode") { sfz::Opcode opcode { "sample123", "dummy" }; @@ -38,6 +56,16 @@ TEST_CASE("[Opcode] Construction") REQUIRE(opcode.parameters == std::vector({ 123 })); } + SECTION("Parameterized opcode with ampersand") + { + sfz::Opcode opcode { "sample&123", "dummy" }; + REQUIRE(opcode.opcode == "sample&123"); + REQUIRE(opcode.lettersOnlyHash == hash("sample&")); + REQUIRE(opcode.value == "dummy"); + REQUIRE(opcode.parameters.size() == 1); + REQUIRE(opcode.parameters == std::vector({ 123 })); + } + SECTION("Parameterized opcode with underscore") { sfz::Opcode opcode { "sample_underscore123", "dummy" };