Add a read_announce_list() to TorrentRead
announce-list is very annoyingly a list of lists. I don't have any useful primitive to manage that case in TorrentRead, so for now I've done a not-so-elegant implementation where I step around the visitor, use my knowledge of the variant and access the outer list directly through boost::get(). I'm not necessarily convinced that this is bad since on the other hand the solution consistent with the rest of the implementation would involve searching for "/[[x]]/[[y]]" which has its own overhead. I mean, variant contains a vector, I can access it normally. Visitor is a convenience thing, I don't see why parser's client code should be obliged to pretend the variant cannot be accessed directly.
This commit is contained in:
parent
f7d90a789d
commit
d04b4d8274
3 changed files with 61 additions and 20 deletions
10
src/main.cpp
10
src/main.cpp
|
@ -49,6 +49,16 @@ int main(int argc, const char* argv[]) {
|
|||
std::cout << "Creation date: " << torrent.read_creation_date() << '\n';
|
||||
std::cout << "Comment: " << torrent.read_comment() << '\n';
|
||||
std::cout << "Announce: " << torrent.read_announce() << '\n';
|
||||
{
|
||||
std::size_t z = 0;
|
||||
for (const std::vector<std::string_view>& sublist : torrent.read_announce_list()) {
|
||||
std::cout << '\t' << ++z << ": < ";
|
||||
for (std::string_view announce : sublist) {
|
||||
std::cout << '"' << announce << "\", ";
|
||||
}
|
||||
std::cout << " >\n";
|
||||
}
|
||||
}
|
||||
std::cout << "Is private: " << std::boolalpha << torrent.read_is_private() << '\n';
|
||||
|
||||
torrent.print(std::cout);
|
||||
|
|
|
@ -87,6 +87,31 @@ std::string_view build_fast_search_path (
|
|||
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::vector<std::string_view> grab_all_strings_in_list (const TorrentValue& node) {
|
||||
const auto path_size = find_int<std::int_fast32_t>("/[[size]]", node);
|
||||
std::vector<std::string_view> retval;
|
||||
retval.reserve(path_size);
|
||||
|
||||
{
|
||||
constexpr char prefix[] = "/[[";
|
||||
constexpr char postfix[] = "]]";
|
||||
constexpr std::size_t prefix_size = sizeof(prefix) / sizeof(prefix[0]) - 1u;
|
||||
constexpr std::size_t postfix_size = sizeof(postfix) / sizeof(postfix[0]) - 1u;
|
||||
char buff[4 + prefix_size + postfix_size];
|
||||
std::string buff2;
|
||||
|
||||
for (std::int_fast32_t z = 0; z < path_size; ++z) {
|
||||
std::string_view piece = find_string(
|
||||
build_fast_search_path(prefix, postfix, z, buff, buff2),
|
||||
node
|
||||
);
|
||||
retval.push_back(piece);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
} //unnamed namespace
|
||||
|
||||
TorrentRead::TorrentRead (std::string_view torrent_path, std::filesystem::path workdir) :
|
||||
|
@ -129,7 +154,6 @@ std::int_fast32_t TorrentRead::read_file_count() const {
|
|||
|
||||
std::vector<std::string_view> TorrentRead::read_file_path(std::size_t index) const {
|
||||
const TorrentValue* path_variant;
|
||||
std::string buff2;
|
||||
|
||||
{
|
||||
constexpr char prefix[] = "/[[";
|
||||
|
@ -140,6 +164,7 @@ std::vector<std::string_view> TorrentRead::read_file_path(std::size_t index) con
|
|||
//see comment in read_file_size()
|
||||
//in this case a search should look like "/[[1234]]/path"
|
||||
char buff[4 + prefix_size + postfix_size];
|
||||
std::string buff2;
|
||||
|
||||
auto found = find_variant(
|
||||
build_fast_search_path(prefix, postfix, index, buff, buff2),
|
||||
|
@ -151,25 +176,7 @@ std::vector<std::string_view> TorrentRead::read_file_path(std::size_t index) con
|
|||
path_variant = &found->get();
|
||||
}
|
||||
|
||||
const auto path_size = find_int<std::int_fast32_t>("/[[size]]", *path_variant);
|
||||
std::vector<std::string_view> retval;
|
||||
retval.reserve(path_size);
|
||||
|
||||
{
|
||||
constexpr char prefix[] = "/[[";
|
||||
constexpr char postfix[] = "]]";
|
||||
constexpr std::size_t prefix_size = sizeof(prefix) / sizeof(prefix[0]) - 1u;
|
||||
constexpr std::size_t postfix_size = sizeof(postfix) / sizeof(postfix[0]) - 1u;
|
||||
char buff[4 + prefix_size + postfix_size];
|
||||
for (std::int_fast32_t z = 0; z < path_size; ++z) {
|
||||
std::string_view piece = find_string(
|
||||
build_fast_search_path(prefix, postfix, z, buff, buff2),
|
||||
*path_variant
|
||||
);
|
||||
retval.push_back(piece);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
return grab_all_strings_in_list(*path_variant);
|
||||
}
|
||||
|
||||
std::string TorrentRead::read_joint_file_path(std::size_t index, char sep) const {
|
||||
|
@ -224,6 +231,29 @@ std::string_view TorrentRead::read_announce() const {
|
|||
return find_string("/announce", m_parsed_values);
|
||||
}
|
||||
|
||||
std::vector<std::vector<std::string_view>> TorrentRead::read_announce_list() const {
|
||||
typedef boost::spirit::x3::forward_ast<std::vector<TorrentValue>> TorrentListType;
|
||||
|
||||
//see https://bittorrent.org/beps/bep_0012.html it's a list of lists
|
||||
auto list_variant = find_variant("/announce-list", m_parsed_values);
|
||||
if (list_variant) {
|
||||
auto* node_list = boost::get<TorrentListType>(&list_variant->get());
|
||||
std::vector<std::vector<std::string_view>> retval;
|
||||
if (node_list) {
|
||||
const auto list_size = static_cast<std::int_fast32_t>(node_list->get().size());
|
||||
retval.reserve(list_size);
|
||||
for (std::int_fast32_t z = 0; z < list_size; ++z) {
|
||||
retval.push_back(grab_all_strings_in_list(node_list->get()[z]));
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
else {
|
||||
//from my tests this node is optional
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
std::time_t TorrentRead::read_creation_date() const {
|
||||
return find_int<std::time_t>("/creation date", m_parsed_values);
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ public:
|
|||
std::string_view read_hashes() const;
|
||||
std::string_view read_created_by() const;
|
||||
std::string_view read_announce() const;
|
||||
std::vector<std::vector<std::string_view>> read_announce_list() const;
|
||||
std::time_t read_creation_date() const;
|
||||
|
||||
private:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue