transmission/libtransmission/file-piece-map.cc

172 lines
4.7 KiB
C++
Raw Normal View History

// This file Copyright © 2021-2022 Mnemosyne LLC.
// It may be used under GPLv2 (SPDX: GPL-2.0), GPLv3 (SPDX: GPL-3.0),
// or any future license endorsed by Mnemosyne LLC.
// License text can be found in the licenses/ folder.
#include <algorithm>
#include <vector>
#include "transmission.h"
#include "block-info.h"
#include "file-piece-map.h"
#include "torrent-metainfo.h"
#include "tr-assert.h"
void tr_file_piece_map::reset(tr_block_info const& block_info, uint64_t const* file_sizes, size_t n_files)
{
file_bytes_.resize(n_files);
file_bytes_.shrink_to_fit();
file_pieces_.resize(n_files);
file_pieces_.shrink_to_fit();
uint64_t offset = 0;
for (tr_file_index_t i = 0; i < n_files; ++i)
{
auto const file_size = file_sizes[i];
auto const begin_byte = offset;
auto const begin_piece = block_info.pieceOf(begin_byte);
auto end_byte = tr_byte_index_t{};
auto end_piece = tr_piece_index_t{};
if (file_size != 0)
{
end_byte = offset + file_size;
auto const final_byte = end_byte - 1;
auto const final_piece = block_info.pieceOf(final_byte);
end_piece = final_piece + 1;
}
else
{
end_byte = begin_byte;
// TODO(ckerr): should end_piece == begin_piece, same as _bytes are?
end_piece = begin_piece + 1;
}
file_pieces_[i] = piece_span_t{ begin_piece, end_piece };
file_bytes_[i] = byte_span_t{ begin_byte, end_byte };
offset += file_size;
}
}
void tr_file_piece_map::reset(tr_torrent_metainfo const& tm)
{
auto const n = tm.fileCount();
auto file_sizes = std::vector<uint64_t>(n);
for (tr_file_index_t i = 0; i < n; ++i)
{
file_sizes[i] = tm.fileSize(i);
}
reset({ tm.totalSize(), tm.pieceSize() }, std::data(file_sizes), std::size(file_sizes));
}
tr_file_piece_map::piece_span_t tr_file_piece_map::pieceSpan(tr_file_index_t file) const
{
return file_pieces_[file];
}
tr_file_piece_map::file_span_t tr_file_piece_map::fileSpan(tr_piece_index_t piece) const
{
auto compare = CompareToSpan<tr_piece_index_t>{};
auto const begin = std::begin(file_pieces_);
auto const& [equal_begin, equal_end] = std::equal_range(begin, std::end(file_pieces_), piece, compare);
fix: sonarcloud warnings (#2260) * fix: add-explicit-keyword-to-constructor warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuB-2farvsyMPiZl&open=AX1tyuB-2farvsyMPiZl * fix: use a structured binding declaration Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuHH2farvsyMPiZm&open=AX1tyuHH2farvsyMPiZm * Fix implicit-conversion-loses-precision warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuH22farvsyMPiZn&open=AX1tyuH22farvsyMPiZn * fix use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuO42farvsyMPiZw&open=AX1tyuO42farvsyMPiZw * fix implicit-conversion-loses-precision warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuO42farvsyMPiZs&open=AX1tyuO42farvsyMPiZs * fix: implicit-conversion-loses-precision warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1tyuO42farvsyMPiZt&open=AX1tyuO42farvsyMPiZt * fix handle-this-exceeption-or-do-not-catch-it warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1y7t12cIz3krp3mVpV&open=AX1y7t12cIz3krp3mVpV * fix make-this-variable-a-reference-to-const warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1y7t12cIz3krp3mVpW&open=AX1y7t12cIz3krp3mVpW * fix replace-redundant-type-with-auto warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1y7t12cIz3krp3mVpY&open=AX1y7t12cIz3krp3mVpY * Fix use-try_emplace-instead-of-emplace warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0WPk3QwxvzFbF6whWN&open=AX0WPk3QwxvzFbF6whWN * Fix: make-this-a-pointer-to-const warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPUXjI_aUyxGBxB4&open=AX0bZPUXjI_aUyxGBxB4 * Fix use-std::make_unique warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0WPk0twxvzFbF6whWC&open=AX0WPk0twxvzFbF6whWC * Fix: replace-push_back-with-emplace_back warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0BraL_0QLXO0pQ_Bfv&open=AX0BraL_0QLXO0pQ_Bfv * Fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPXajI_aUyxGBxB8&open=AX0bZPXajI_aUyxGBxB8 * Fix: replace-redundant-type-with-auto warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPXajI_aUyxGBxB9&open=AX0bZPXajI_aUyxGBxB9 * Fix: replace-emplace-with-try_emplace warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPXajI_aUyxGBxB_&open=AX0bZPXajI_aUyxGBxB_ * Fix: extract-assignment-from-operation warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0bZPXajI_aUyxGBxCA&open=AX0bZPXajI_aUyxGBxCA * Fix use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX1op6_hUBCnp-Grmra8&open=AX1op6_hUBCnp-Grmra8 * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0L8qgMUnpKTxYiu5CN&open=AX0L8qgMUnpKTxYiu5CN * Revert "Fix use-std::make_unique warning" This reverts commit 463a742f344e495416621825a7203d168f26343f. * fix: make-parameter-a-pointer-to-const warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX06St241usi2gyYkPTZ&open=AX06St241usi2gyYkPTZ * fix: make-parameter-a-pointer-to-const warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX06St241usi2gyYkPTa&open=AX06St241usi2gyYkPTa * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX01Itn2f_SST5i7BN1o&open=AX01Itn2f_SST5i7BN1o * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AXziv55-MuQoG-Y-NgLX&open=AXziv55-MuQoG-Y-NgLX * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AX0_a_JGNJn7rAzml_68&open=AX0_a_JGNJn7rAzml_68 * fix: replace-redundant-type-with-auto warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AXzyMRYbK9dvryvWm8XA&open=AXzyMRYbK9dvryvWm8XA * fix: use-init-statement warning Xref: https://sonarcloud.io/project/issues?id=transmission_transmission&issues=AXziv52fMuQoG-Y-NgLW&open=AXziv52fMuQoG-Y-NgLW
2021-12-01 23:11:57 +00:00
return { tr_piece_index_t(std::distance(begin, equal_begin)), tr_piece_index_t(std::distance(begin, equal_end)) };
}
tr_file_piece_map::file_offset_t tr_file_piece_map::fileOffset(uint64_t offset) const
{
auto compare = CompareToSpan<uint64_t>{};
auto const begin = std::begin(file_bytes_);
auto const it = std::lower_bound(begin, std::end(file_bytes_), offset, compare);
tr_file_index_t const file_index = std::distance(begin, it);
auto const file_offset = offset - it->begin;
return file_offset_t{ file_index, file_offset };
}
/***
****
***/
tr_file_priorities::tr_file_priorities(tr_file_piece_map const* fpm)
{
reset(fpm);
}
void tr_file_priorities::reset(tr_file_piece_map const* fpm)
{
fpm_ = fpm;
auto const n = std::size(*fpm_);
priorities_.resize(n);
priorities_.shrink_to_fit();
std::fill_n(std::begin(priorities_), n, TR_PRI_NORMAL);
}
void tr_file_priorities::set(tr_file_index_t file, tr_priority_t priority)
{
priorities_[file] = priority;
}
void tr_file_priorities::set(tr_file_index_t const* files, size_t n, tr_priority_t priority)
{
for (size_t i = 0; i < n; ++i)
{
set(files[i], priority);
}
}
tr_priority_t tr_file_priorities::filePriority(tr_file_index_t file) const
{
TR_ASSERT(file < std::size(priorities_));
return priorities_[file];
}
tr_priority_t tr_file_priorities::piecePriority(tr_piece_index_t piece) const
{
auto const [begin_idx, end_idx] = fpm_->fileSpan(piece);
auto const begin = std::begin(priorities_) + begin_idx;
auto const end = std::begin(priorities_) + end_idx;
auto const it = std::max_element(begin, end);
if (it == end)
{
return TR_PRI_NORMAL;
}
return *it;
}
/***
****
***/
void tr_files_wanted::reset(tr_file_piece_map const* fpm)
{
fpm_ = fpm;
wanted_ = tr_bitfield{ std::size(*fpm) };
wanted_.setHasAll(); // by default we want all files
}
void tr_files_wanted::set(tr_file_index_t file, bool wanted)
{
wanted_.set(file, wanted);
}
void tr_files_wanted::set(tr_file_index_t const* files, size_t n, bool wanted)
{
for (size_t i = 0; i < n; ++i)
{
set(files[i], wanted);
}
}
bool tr_files_wanted::fileWanted(tr_file_index_t file) const
{
return wanted_.test(file);
}
bool tr_files_wanted::pieceWanted(tr_piece_index_t piece) const
{
auto const [begin, end] = fpm_->fileSpan(piece);
return wanted_.count(begin, end) != 0;
}