Repository: xbmc/xbmc
File: xbmc/utils/LegacyPathTranslation.cpp (C++)

Code before:
    {"videodb://5", "videodb://recentlyaddedepisodes"},
    {"videodb://6", "videodb://recentlyaddedmusicvideos"}};

// ATTENTION: Make sure the longer match strings go first
// because the string match is performed with StringUtils::StartsWith()
const auto s_musicDbTranslator =
    std::unordered_map<std::string, std::string>{{"musicdb://10", "musicdb://singles"},
                                                 {"musicdb://1", "musicdb://genres"},
                                                 {"musicdb://2", "musicdb://artists"},
                                                 {"musicdb://3", "musicdb://albums"},
                                                 {"musicdb://4", "musicdb://songs"},
                                                 {"musicdb://5/1", "musicdb://top100/albums"},
                                                 {"musicdb://5/2", "musicdb://top100/songs"},
                                                 {"musicdb://5", "musicdb://top100"},
                                                 {"musicdb://6", "musicdb://recentlyaddedalbums"},
                                                 {"musicdb://7", "musicdb://recentlyplayedalbums"},
                                                 {"musicdb://8", "musicdb://compilations"},
                                                 {"musicdb://9", "musicdb://years"}};

std::string TranslatePath(const std::string& legacyPath,
                          const std::unordered_map<std::string, std::string>& translationMap)
{
  std::string newPath = legacyPath;
  const std::string lowPath = StringUtils::ToLower(legacyPath);
  const auto it = std::find_if(translationMap.begin(), translationMap.end(),
                               [&lowPath](const auto& e) { return lowPath.starts_with(e.first); });
  if (it != translationMap.end())
    StringUtils::Replace(newPath, it->first, it->second);

  return newPath;
}

} // namespace

std::string CLegacyPathTranslation::TranslateVideoDbPath(const CURL& legacyPath)
{
  return TranslatePath(legacyPath.Get(), s_videoDbTranslator);
}

std::string CLegacyPathTranslation::TranslateMusicDbPath(const CURL& legacyPath)
{
  return TranslatePath(legacyPath.Get(), s_musicDbTranslator);
}

std::string CLegacyPathTranslation::TranslateVideoDbPath(const std::string& legacyPath)
{
  return TranslatePath(legacyPath, s_videoDbTranslator);
}

std::string CLegacyPathTranslation::TranslateMusicDbPath(const std::string& legacyPath)
{

Review comment (suggestion):
the old way was using StartsWithNoCase it was converting to lowercase both values,
now you are comparing one lower string, and you assume that the other value is lowered, but imo not so correct, an oversight can cause problems

on "translator" lists above there are comment "ATTENTION:...." that refer to StartsWithNoCase but if you change method all comments should be updated

Code after:
    {"videodb://5", "videodb://recentlyaddedepisodes"},
    {"videodb://6", "videodb://recentlyaddedmusicvideos"}};

// ATTENTION: Make sure the longer match strings go first
// because the string match is performed with ::starts_with()
const auto s_musicDbTranslator =
    std::unordered_map<std::string, std::string>{{"musicdb://10", "musicdb://singles"},
                                                 {"musicdb://1", "musicdb://genres"},
                                                 {"musicdb://2", "musicdb://artists"},
                                                 {"musicdb://3", "musicdb://albums"},
                                                 {"musicdb://4", "musicdb://songs"},
                                                 {"musicdb://5/1", "musicdb://top100/albums"},
                                                 {"musicdb://5/2", "musicdb://top100/songs"},
                                                 {"musicdb://5", "musicdb://top100"},
                                                 {"musicdb://6", "musicdb://recentlyaddedalbums"},
                                                 {"musicdb://7", "musicdb://recentlyplayedalbums"},
                                                 {"musicdb://8", "musicdb://compilations"},
                                                 {"musicdb://9", "musicdb://years"}};

std::string TranslatePath(const std::string& legacyPath,
                          const std::unordered_map<std::string, std::string>& translationMap)
{
  std::string newPath = legacyPath;
  const std::string lowPath = StringUtils::ToLower(legacyPath);
  const auto it = std::find_if(translationMap.begin(), translationMap.end(),
                               [&lowPath](const auto& e) { return lowPath.starts_with(e.first); });
  if (it != translationMap.end())
    StringUtils::Replace(newPath, it->first, it->second);

  return newPath;
}

} // namespace

std::string CLegacyPathTranslation::TranslateVideoDbPath(const CURL& legacyPath)
{
  return TranslatePath(legacyPath.Get(), s_videoDbTranslator);
}

std::string CLegacyPathTranslation::TranslateMusicDbPath(const CURL& legacyPath)
{
  return TranslatePath(legacyPath.Get(), s_musicDbTranslator);
}

std::string CLegacyPathTranslation::TranslateVideoDbPath(const std::string& legacyPath)
{
  return TranslatePath(legacyPath, s_videoDbTranslator);
}

std::string CLegacyPathTranslation::TranslateMusicDbPath(const std::string& legacyPath)
{