1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

LV2 Client: Sanitise parameter IDs to ensure validity of generated ttl files

This commit is contained in:
reuk 2022-12-07 19:17:13 +00:00
parent 676e10fdd9
commit b70ab79173
No known key found for this signature in database
GPG key ID: 9ADCD339CFC98A11
2 changed files with 62 additions and 1 deletions

View file

@ -124,7 +124,14 @@ public:
*/
static String getIri (const AudioProcessorParameter& param)
{
return URL::addEscapeChars (LegacyAudioParameter::getParamID (&param, false), true);
const auto urlSanitised = URL::addEscapeChars (LegacyAudioParameter::getParamID (&param, false), true);
const auto ttlSanitised = lv2_shared::sanitiseStringAsTtlName (urlSanitised);
// If this is hit, the parameter ID could not be represented directly in the plugin ttl.
// We'll replace offending characters with '_'.
jassert (urlSanitised == ttlSanitised);
return ttlSanitised;
}
void setValueFromHost (LV2_URID urid, float value) noexcept
@ -217,6 +224,11 @@ private:
result.push_back (urid);
}
// If this is hit, some parameters have duplicate IDs.
// This may be because the IDs resolve to the same string when removing characters that
// are invalid in a TTL name.
jassert (std::set<LV2_URID> (result.begin(), result.end()).size() == result.size());
return result;
}();
const std::map<LV2_URID, size_t> uridToIndexMap = [&]

View file

@ -615,6 +615,55 @@ static inline std::vector<ParsedGroup> findStableBusOrder (const String& mainGro
return result;
}
/* See https://www.w3.org/TeamSubmission/turtle/#sec-grammar-grammar
*/
static inline bool isNameStartChar (juce_wchar input)
{
return ('A' <= input && input <= 'Z')
|| input == '_'
|| ('a' <= input && input <= 'z')
|| (0x000c0 <= input && input <= 0x000d6)
|| (0x000d8 <= input && input <= 0x000f6)
|| (0x000f8 <= input && input <= 0x000ff)
|| (0x00370 <= input && input <= 0x0037d)
|| (0x0037f <= input && input <= 0x01fff)
|| (0x0200c <= input && input <= 0x0200d)
|| (0x02070 <= input && input <= 0x0218f)
|| (0x02c00 <= input && input <= 0x02fef)
|| (0x03001 <= input && input <= 0x0d7ff)
|| (0x0f900 <= input && input <= 0x0fdcf)
|| (0x0fdf0 <= input && input <= 0x0fffd)
|| (0x10000 <= input && input <= 0xeffff);
}
static inline bool isNameChar (juce_wchar input)
{
return isNameStartChar (input)
|| input == '-'
|| ('0' <= input && input <= '9')
|| input == 0x000b7
|| (0x00300 <= input && input <= 0x0036f)
|| (0x0203f <= input && input <= 0x02040);
}
static inline String sanitiseStringAsTtlName (const String& input)
{
if (input.isEmpty())
return {};
std::vector<juce_wchar> sanitised;
sanitised.reserve (static_cast<size_t> (input.length()));
sanitised.push_back (isNameStartChar (input[0]) ? input[0] : '_');
std::for_each (std::begin (input) + 1, std::end (input), [&] (juce_wchar x)
{
sanitised.push_back (isNameChar (x) ? x : '_');
});
return String (CharPointer_UTF32 { sanitised.data() }, sanitised.size());
}
}
}