2023-11-01 21:11:11 +00:00
|
|
|
// This file Copyright © Mnemosyne LLC.
|
2022-08-08 18:05:39 +00:00
|
|
|
// It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
|
2022-01-20 18:27:56 +00:00
|
|
|
// or any future license endorsed by Mnemosyne LLC.
|
|
|
|
// License text can be found in the licenses/ folder.
|
2021-11-24 14:48:52 +00:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2022-04-08 01:50:26 +00:00
|
|
|
#include <cstdint> // uint32_t, uint64_t
|
|
|
|
|
2023-11-03 17:03:26 +00:00
|
|
|
#include "libtransmission/transmission.h"
|
2021-11-24 14:48:52 +00:00
|
|
|
|
|
|
|
struct tr_block_info
|
|
|
|
{
|
2022-04-14 01:22:59 +00:00
|
|
|
public:
|
2023-12-06 04:06:27 +00:00
|
|
|
static auto constexpr BlockSize = uint32_t{ 1024U * 16U };
|
2021-11-24 14:48:52 +00:00
|
|
|
|
2024-03-09 16:27:20 +00:00
|
|
|
tr_block_info() noexcept
|
|
|
|
{
|
|
|
|
}
|
2022-04-14 01:22:59 +00:00
|
|
|
|
2023-12-06 04:06:27 +00:00
|
|
|
tr_block_info(uint64_t const total_size_in, uint32_t const piece_size_in) noexcept
|
2021-11-24 14:48:52 +00:00
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
init_sizes(total_size_in, piece_size_in);
|
2021-11-24 14:48:52 +00:00
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] constexpr auto block_count() const noexcept
|
2022-01-07 19:13:37 +00:00
|
|
|
{
|
2022-04-14 01:22:59 +00:00
|
|
|
return n_blocks_;
|
2022-01-07 19:13:37 +00:00
|
|
|
}
|
|
|
|
|
2023-12-06 04:06:27 +00:00
|
|
|
[[nodiscard]] constexpr auto block_size(tr_block_index_t const block) const noexcept
|
2022-01-07 19:13:37 +00:00
|
|
|
{
|
2023-12-06 04:06:27 +00:00
|
|
|
return block + 1U == n_blocks_ ? final_block_size_ : BlockSize;
|
2022-01-07 19:13:37 +00:00
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] constexpr auto piece_count() const noexcept
|
2022-01-07 19:13:37 +00:00
|
|
|
{
|
2022-04-14 01:22:59 +00:00
|
|
|
return n_pieces_;
|
2022-01-07 19:13:37 +00:00
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] constexpr auto piece_size() const noexcept
|
2021-11-24 14:48:52 +00:00
|
|
|
{
|
2022-04-14 01:22:59 +00:00
|
|
|
return piece_size_;
|
2021-11-24 14:48:52 +00:00
|
|
|
}
|
|
|
|
|
2023-12-06 04:06:27 +00:00
|
|
|
[[nodiscard]] constexpr auto piece_size(tr_piece_index_t const piece) const noexcept
|
2021-11-24 14:48:52 +00:00
|
|
|
{
|
2023-12-06 04:06:27 +00:00
|
|
|
return piece + 1U == n_pieces_ ? final_piece_size_ : piece_size();
|
2022-04-14 01:22:59 +00:00
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] constexpr auto total_size() const noexcept
|
2022-04-14 01:22:59 +00:00
|
|
|
{
|
|
|
|
return total_size_;
|
2021-11-24 14:48:52 +00:00
|
|
|
}
|
|
|
|
|
2022-02-18 23:17:19 +00:00
|
|
|
struct Location
|
2021-11-24 14:48:52 +00:00
|
|
|
{
|
2022-11-03 23:08:02 +00:00
|
|
|
[[nodiscard]] constexpr bool operator==(Location const& that) const noexcept
|
2021-12-06 03:12:21 +00:00
|
|
|
{
|
2022-02-18 23:17:19 +00:00
|
|
|
return this->byte == that.byte;
|
2021-12-06 03:12:21 +00:00
|
|
|
}
|
|
|
|
|
2022-11-03 23:08:02 +00:00
|
|
|
[[nodiscard]] constexpr bool operator<(Location const& that) const noexcept
|
2021-12-06 03:12:21 +00:00
|
|
|
{
|
2022-02-18 23:17:19 +00:00
|
|
|
return this->byte < that.byte;
|
2021-12-06 03:12:21 +00:00
|
|
|
}
|
2023-12-06 04:06:27 +00:00
|
|
|
|
|
|
|
uint64_t byte = {};
|
|
|
|
|
|
|
|
tr_piece_index_t piece = {};
|
|
|
|
uint32_t piece_offset = {};
|
|
|
|
|
|
|
|
tr_block_index_t block = {};
|
|
|
|
uint32_t block_offset = {};
|
2022-02-18 23:17:19 +00:00
|
|
|
};
|
2021-12-06 03:12:21 +00:00
|
|
|
|
2022-08-20 15:40:18 +00:00
|
|
|
// Location of the torrent's nth byte
|
2023-12-06 04:06:27 +00:00
|
|
|
[[nodiscard]] constexpr auto byte_loc(uint64_t const byte_idx) const noexcept
|
2022-08-20 15:40:18 +00:00
|
|
|
{
|
|
|
|
auto loc = Location{};
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
if (is_initialized())
|
2022-08-20 15:40:18 +00:00
|
|
|
{
|
|
|
|
loc.byte = byte_idx;
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
if (byte_idx == total_size()) // handle 0-byte files at the end of a torrent
|
2022-08-20 15:40:18 +00:00
|
|
|
{
|
2023-12-06 04:06:27 +00:00
|
|
|
loc.block = block_count() - 1U;
|
|
|
|
loc.piece = piece_count() - 1U;
|
2022-08-20 15:40:18 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-12-31 20:04:26 +00:00
|
|
|
loc.block = static_cast<tr_block_index_t>(byte_idx / BlockSize);
|
|
|
|
loc.piece = static_cast<tr_piece_index_t>(byte_idx / piece_size());
|
2022-08-20 15:40:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
loc.block_offset = static_cast<uint32_t>(loc.byte - (uint64_t{ loc.block } * BlockSize));
|
2023-04-23 01:25:55 +00:00
|
|
|
loc.piece_offset = static_cast<uint32_t>(loc.byte - (uint64_t{ loc.piece } * piece_size()));
|
2022-08-20 15:40:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return loc;
|
|
|
|
}
|
|
|
|
|
2022-02-18 23:17:19 +00:00
|
|
|
// Location of the first byte in `block`.
|
2023-12-06 04:06:27 +00:00
|
|
|
[[nodiscard]] constexpr auto block_loc(tr_block_index_t const block) const noexcept
|
2022-08-20 15:40:18 +00:00
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
return byte_loc(uint64_t{ block } * BlockSize);
|
2022-08-20 15:40:18 +00:00
|
|
|
}
|
2021-11-24 14:48:52 +00:00
|
|
|
|
2022-02-18 23:17:19 +00:00
|
|
|
// Location of the first byte (+ optional offset and length) in `piece`
|
2023-12-06 04:06:27 +00:00
|
|
|
[[nodiscard]] constexpr auto piece_loc(tr_piece_index_t piece, uint32_t offset = {}, uint32_t length = {}) const noexcept
|
2022-08-20 15:40:18 +00:00
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
return byte_loc(uint64_t{ piece } * piece_size() + offset + length);
|
2022-08-20 15:40:18 +00:00
|
|
|
}
|
2022-02-23 13:38:18 +00:00
|
|
|
|
2023-12-06 04:06:27 +00:00
|
|
|
[[nodiscard]] constexpr tr_block_span_t block_span_for_piece(tr_piece_index_t const piece) const noexcept
|
2022-08-20 15:40:18 +00:00
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
if (!is_initialized())
|
2022-08-20 15:40:18 +00:00
|
|
|
{
|
|
|
|
return { 0U, 0U };
|
|
|
|
}
|
|
|
|
|
2023-12-06 04:06:27 +00:00
|
|
|
return { piece_loc(piece).block, piece_last_loc(piece).block + 1U };
|
2022-08-20 15:40:18 +00:00
|
|
|
}
|
|
|
|
|
2023-12-06 04:06:27 +00:00
|
|
|
[[nodiscard]] constexpr tr_byte_span_t byte_span_for_piece(tr_piece_index_t const piece) const noexcept
|
2022-08-20 15:40:18 +00:00
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
if (!is_initialized())
|
2022-08-20 15:40:18 +00:00
|
|
|
{
|
|
|
|
return { 0U, 0U };
|
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
auto const offset = piece_loc(piece).byte;
|
|
|
|
return { offset, offset + piece_size(piece) };
|
2022-08-20 15:40:18 +00:00
|
|
|
}
|
2021-11-24 14:48:52 +00:00
|
|
|
|
2022-04-14 01:22:59 +00:00
|
|
|
private:
|
2023-12-06 04:06:27 +00:00
|
|
|
void init_sizes(uint64_t total_size_in, uint32_t piece_size_in) noexcept;
|
|
|
|
|
2022-02-18 23:17:19 +00:00
|
|
|
// Location of the last byte in `piece`.
|
2023-12-06 04:06:27 +00:00
|
|
|
[[nodiscard]] constexpr Location piece_last_loc(tr_piece_index_t const piece) const noexcept
|
2021-11-24 14:48:52 +00:00
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
return byte_loc(static_cast<uint64_t>(piece) * piece_size() + piece_size(piece) - 1);
|
2022-01-07 19:13:37 +00:00
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] constexpr bool is_initialized() const noexcept
|
2022-02-18 23:17:19 +00:00
|
|
|
{
|
2023-12-06 04:06:27 +00:00
|
|
|
return piece_size_ != 0U;
|
2022-02-18 23:17:19 +00:00
|
|
|
}
|
2023-12-06 04:06:27 +00:00
|
|
|
|
|
|
|
uint64_t total_size_ = {};
|
|
|
|
|
|
|
|
tr_block_index_t n_blocks_ = {};
|
|
|
|
tr_piece_index_t n_pieces_ = {};
|
|
|
|
|
|
|
|
uint32_t final_block_size_ = {};
|
|
|
|
|
|
|
|
uint32_t piece_size_ = {};
|
|
|
|
uint32_t final_piece_size_ = {};
|
2021-11-24 14:48:52 +00:00
|
|
|
};
|