Repository: xbmc/xbmc
File: xbmc/addons/Repository.cpp (C++)

Code before:

  return true;
}

bool CRepository::FetchIndex(const RepositoryDirInfo& repo,
                             std::string const& digest,
                             std::vector<AddonInfoPtr>& addons) noexcept
{
  std::string response;
  CFile file;
  if (!file.Open(repo.info))
  {
    CLog::Log(LOGERROR, "CRepository: failed to read {}", repo.info);
    return false;
  }

  // we intentionally avoid using file.GetLength() for
  // Transfer-Encoding: chunked servers.
  std::stringstream ss;
  char temp[1024];
  int read;
  while ((read = file.Read(temp, sizeof(temp))) > 0)
    ss.write(temp, read);
  if (read <= -1)
    return false;
  response = ss.str();

  if (repo.checksumType != CDigest::Type::INVALID)
  {
    std::string actualDigest = CDigest::Calculate(repo.checksumType, response);
    if (!StringUtils::EqualsNoCase(digest, actualDigest))
    {
      CLog::Log(LOGERROR, "CRepository: {} index has wrong digest {}, expected: {}", repo.info, actualDigest, digest);
      return false;
    }
  }

  if (URIUtils::HasExtension(repo.info, ".gz") ||
      CMime::GetFileTypeFromMime(file.GetProperty(XFILE::FILE_PROPERTY_MIME_TYPE)) ==
          CMime::EFileType::FileTypeGZip)
  {
    CLog::Log(LOGDEBUG, "CRepository '{}' is gzip. decompressing", repo.info);
    std::string buffer;
    if (!CZipFile::DecompressGzip(response, buffer))
    {
      CLog::Log(LOGERROR, "CRepository: failed to decompress gzip from '{}'", repo.info);
      return false;
    }
    response = std::move(buffer);
  }


Review comment (suggestion):
To avoid copying the string into `response`:
```suggestion
  response = std::move(ss).str();
```

Code after:

  return true;
}

bool CRepository::FetchIndex(const RepositoryDirInfo& repo,
                             std::string const& digest,
                             std::vector<AddonInfoPtr>& addons) noexcept
{
  XFILE::CCurlFile http;

  std::string response;
  if (!http.Get(repo.info, response))
  {
    CLog::Log(LOGERROR, "CRepository: failed to read {}", repo.info);
    return false;
  }

  if (repo.checksumType != CDigest::Type::INVALID)
  {
    std::string actualDigest = CDigest::Calculate(repo.checksumType, response);
    if (!StringUtils::EqualsNoCase(digest, actualDigest))
    {
      CLog::Log(LOGERROR, "CRepository: {} index has wrong digest {}, expected: {}", repo.info, actualDigest, digest);
      return false;
    }
  }

  if (URIUtils::HasExtension(repo.info, ".gz")
      || CMime::GetFileTypeFromMime(http.GetProperty(XFILE::FILE_PROPERTY_MIME_TYPE)) == CMime::EFileType::FileTypeGZip)
  {
    CLog::Log(LOGDEBUG, "CRepository '{}' is gzip. decompressing", repo.info);
    std::string buffer;
    if (!CZipFile::DecompressGzip(response, buffer))
    {
      CLog::Log(LOGERROR, "CRepository: failed to decompress gzip from '{}'", repo.info);
      return false;
    }
    response = std::move(buffer);
  }

  return CServiceBroker::GetAddonMgr().AddonsFromRepoXML(repo, response, addons);
}

CRepository::FetchStatus CRepository::FetchIfChanged(const std::string& oldChecksum,
                                                     std::string& checksum,
                                                     std::vector<AddonInfoPtr>& addons,
                                                     int& recheckAfter) const
{
  checksum = "";
  std::vector<std::tuple<RepositoryDirInfo const&, std::string>> dirChecksums;
  std::vector<int> recheckAfterTimes;