Fixed lyrics parsing on very long tags

This commit is contained in:
emeric
2024-11-11 10:02:11 +01:00
parent 1842c0ef7d
commit 3ff58a131a
2 changed files with 70 additions and 39 deletions
+42 -39
View File
@@ -34,50 +34,53 @@ namespace lms::metadata
namespace
{
std::string_view getSubmatchString(const std::csub_match& submatch)
// Parse a single line with a tag like [ar: Artist] and set the appropriate fields in the Lyrics object
bool parseTag(std::string_view line, Lyrics& lyrics)
{
assert(submatch.matched);
return std::string_view{ submatch.first, static_cast<std::string_view::size_type>(submatch.length()) };
}
if (line.empty())
return false;
// Parse a single line with ID tags like [ar: Artist] and set the appropriate fields in the Lyrics object
bool parseIDTag(std::string_view line, Lyrics& lyrics)
{
static const std::regex idTagRegex{ R"(^\[([a-zA-Z_]+):(.+?)\])" };
std::cmatch match;
if (line.front() != '[' || line.back() != ']') // consider lines are trimmed
return false;
if (std::regex_search(line.data(), line.data() + line.size(), match, idTagRegex))
const auto separator{ line.find(':') };
if (separator == std::string_view::npos)
return false;
const std::string_view tagType{ core::stringUtils::stringTrim(line.substr(1, separator - 1)) };
const std::string_view tagValue{ core::stringUtils::stringTrim(line.substr(separator + 1, line.size() - separator - 2)) };
if (tagType.empty())
return false;
// check for timestamps
if (std::any_of(tagType.begin(), tagType.end(), [](char c) { return std::isdigit(c); }))
return false;
if (tagType == "ar")
{
std::string_view tagType{ getSubmatchString(match[1]) };
std::string_view tagValue{ core::stringUtils::stringTrim(getSubmatchString(match[2])) };
if (tagType == "ar")
{
lyrics.displayArtist = tagValue;
}
else if (tagType == "al")
{
lyrics.displayAlbum = tagValue;
}
else if (tagType == "ti")
{
lyrics.displayTitle = tagValue;
}
else if (tagType == "la")
{
lyrics.language = tagValue;
}
else if (tagType == "offset")
{
if (const auto value{ core::stringUtils::readAs<int>(tagValue) })
lyrics.offset = std::chrono::milliseconds{ *value };
}
// not interrested by other tags like 'duration', 'id', etc.
return true;
lyrics.displayArtist = tagValue;
}
else if (tagType == "al")
{
lyrics.displayAlbum = tagValue;
}
else if (tagType == "ti")
{
lyrics.displayTitle = tagValue;
}
else if (tagType == "la")
{
lyrics.language = tagValue;
}
else if (tagType == "offset")
{
if (const auto value{ core::stringUtils::readAs<int>(tagValue) })
lyrics.offset = std::chrono::milliseconds{ *value };
}
// not interrested by other tags like 'duration', 'id', etc.
return false;
return true;
}
// Parse timestamps from a line and return the associated times in milliseconds
@@ -172,7 +175,7 @@ namespace lms::metadata
if (currentState == State::None && trimmedLine.empty())
continue;
if (parseIDTag(trimmedLine, lyrics))
if (parseTag(trimmedLine, lyrics))
continue;
extractTimestamps(trimmedLine, timestamps);