Split project into cli and shared object

Since it's a .so now I also added a C API that wraps TorrentRead
This commit is contained in:
King_DuckZ 2025-04-07 13:22:47 +01:00
commit 5a78ef04de
17 changed files with 355 additions and 20 deletions

View file

@ -1,5 +1,5 @@
project('ducktorrent', 'cpp', project('ducktorrent', 'cpp',
version: '0.2.0', version: '0.2.1',
meson_version: '>=0.63.0', meson_version: '>=0.63.0',
default_options: [ default_options: [
'buildtype=release', 'buildtype=release',

View file

@ -15,7 +15,7 @@
* along with ducktorrent. If not, see <http://www.gnu.org/licenses/>. * along with ducktorrent. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "torrent_read.hpp" #include "ducktorrent/torrent_read.hpp"
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>

9
src/cli/meson.build Normal file
View file

@ -0,0 +1,9 @@
executable(meson.project_name(),
'main.cpp',
dependencies: [
boost_dep,
libstriezel_dep,
ducktorrent_dep,
],
install: true,
)

View file

@ -0,0 +1,213 @@
/* Copyright 2025, Michele "King_DuckZ" Santullo
* This file is part of ducktorrent.
*
* Ducktorrent is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Ducktorrent is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ducktorrent. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ducktorrent/torrent_read.h"
#include "ducktorrent/torrent_read.hpp"
#include <memory>
#include <ciso646>
#include <string_view>
#include <iostream>
#include <string>
#include <vector>
extern "C"
struct dt_torrent {
dt_torrent (std::string_view path) :
reader(path, "")
{ }
duck::TorrentRead reader;
std::string str_buff;
std::vector<dt_string> vec_buff;
std::vector<std::vector<dt_string>> announce_list_buff;
};
extern "C"
struct dt_torrent* dt_make_reader_from_path (dt_string path) {
try {
std::string_view path_sv(path.str, path.len);
return new dt_torrent(path_sv);
}
catch (...) {
return nullptr;
}
}
extern "C"
void dt_free_torrent_read (struct dt_torrent* t) {
delete t;
}
extern "C"
void dt_print_to_stdout(struct dt_torrent* t) {
try {
t->reader.print(std::cout);
}
catch (...) {
}
}
extern "C"
size_t dt_read_piece_length(struct dt_torrent* t) {
try {
return t->reader.read_piece_length();
}
catch (...) {
return -1;
}
}
extern "C"
int_fast32_t dt_read_file_count(struct dt_torrent* t) {
try {
return t->reader.read_file_count();
}
catch (...) {
return -1;
}
}
extern "C"
dt_string_list dt_read_file_path(struct dt_torrent* t, size_t index) {
try {
auto vec = t->reader.read_file_path(index);
t->vec_buff.clear();
t->vec_buff.reserve(vec.size());
for (std::string_view s : vec) {
t->vec_buff.emplace_back(s.data(), s.size());
}
return {t->vec_buff.data(), t->vec_buff.size()};
}
catch (...) {
return {nullptr, 0};
}
}
extern "C"
dt_string dt_read_joint_file_path(struct dt_torrent* t, size_t index, char sep){
try {
t->str_buff = t->reader.read_joint_file_path(index, sep);
return {t->str_buff.c_str(), t->str_buff.size()};
}
catch (...) {
return {nullptr, 0};
}
}
extern "C"
size_t dt_read_file_size(struct dt_torrent* t, size_t index) {
try {
return t->reader.read_file_size(index);
}
catch (...) {
return -1;
}
}
extern "C"
int dt_read_is_private(struct dt_torrent* t) {
try {
return static_cast<int>(t->reader.read_is_private());
}
catch (...) {
return -1;
}
}
extern "C"
dt_string dt_read_comment(struct dt_torrent* t) {
try {
std::string_view comment = t->reader.read_comment();
return dt_string{comment.data(), comment.size()};
}
catch (...) {
return {nullptr, 0};
}
}
extern "C"
dt_string dt_read_hashes(struct dt_torrent* t) {
try {
std::string_view hashes = t->reader.read_hashes();
return dt_string{hashes.data(), hashes.size()};
}
catch (...) {
return {nullptr, 0};
}
}
extern "C"
dt_string dt_read_created_by(struct dt_torrent* t) {
try {
std::string_view created = t->reader.read_created_by();
return dt_string{created.data(), created.size()};
}
catch (...) {
return {nullptr, 0};
}
}
extern "C"
dt_string dt_read_announce(struct dt_torrent* t) {
try {
std::string_view announce = t->reader.read_announce();
return dt_string{announce.data(), announce.size()};
}
catch (...) {
return {nullptr, 0};
}
}
extern "C"
size_t dt_read_announce_list_size(struct dt_torrent* t) {
try {
return t->reader.read_announce_list_size();
}
catch (...) {
return -1;
}
}
extern "C"
dt_string_list dt_read_announce_list(struct dt_torrent* t, size_t index) {
try {
if (t->announce_list_buff.empty()) {
t->announce_list_buff.reserve(t->reader.read_announce_list_size());
for (const auto& sublist : t->reader.read_announce_list()) {
t->announce_list_buff.emplace_back();
for (std::string_view item : sublist) {
t->announce_list_buff.back().emplace_back(item.data(), item.size());
}
}
}
return {t->announce_list_buff[index].data(), t->announce_list_buff[index].size()};
}
catch (...) {
return {nullptr, 0};
}
}
extern "C"
time_t dt_read_creation_date(struct dt_torrent* t) {
try {
return t->reader.read_creation_date();
}
catch (...) {
return {};
}
}

View file

@ -0,0 +1,85 @@
/* Copyright 2025, Michele "King_DuckZ" Santullo
* This file is part of ducktorrent.
*
* Ducktorrent is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Ducktorrent is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ducktorrent. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
//c wrapper for torrent_read.hpp
#if defined(__cplusplus)
extern "C" {
#endif
#include <stddef.h>
#include <stdint.h>
#include <time.h>
/* Strings and lists returned by functions in this file should be considered
* temporary and might become invalid on any subsequent function call. There is
* no thread safety mechanism so you should protect calls with your own mutex.
* With that said, if you're interested in avoiding unnecessary memory
* allocations and copies, there are cases where the above is not true. Rather
* than making a list of functions the whose output is guaranteed to not change,
* the rule for figuring out what might not need copying is the following:
* wrapper functions around C++ methods that return an std::string_view do not
* need to be copied. That is because the string returned by the C++ side is
* already a reference into the in-memory torrent file buffer. This however
* means that these particular strings are *not* null-terminated.
* As these functions do not write to the C wrapper's internal string cache and
* they only read from the parsed tree, it is also safe to call them in a
* multithreaded context.
* One more exception to the above rule is the special case of
* dt_read_announce_list(), since it returs a list of lists this C wrapper
* caches the whole thing on the first call and subsequent calls will not hit
* the C++ side again. As said, the list side of things is cached in the C
* wrapper, and since the inner type returned by the C++ method is
* std::string_view this means the strings won't change either, therefore it is
* safe to not copy these items either for as long as the dt_torrent context
* stays alive.
*/
typedef struct {
const char* str;
size_t len;
} dt_string;
typedef struct {
const dt_string* lst;
size_t len;
} dt_string_list;
/*struct dt_torrent_read* dt_make_reader_from_data (const char* raw_data, size_t raw_data_size);*/
struct dt_torrent* dt_make_reader_from_path (dt_string path);
void dt_free_torrent_read (struct dt_torrent*);
void dt_print_to_stdout(struct dt_torrent*);
size_t dt_read_piece_length(struct dt_torrent*);
int_fast32_t dt_read_file_count(struct dt_torrent*);
dt_string_list dt_read_file_path(struct dt_torrent*, size_t index);
dt_string dt_read_joint_file_path(struct dt_torrent*, size_t index, char sep);
size_t dt_read_file_size(struct dt_torrent*, size_t index);
int dt_read_is_private(struct dt_torrent*);
dt_string dt_read_comment(struct dt_torrent*);
dt_string dt_read_hashes(struct dt_torrent*);
dt_string dt_read_created_by(struct dt_torrent*);
dt_string dt_read_announce(struct dt_torrent*);
size_t dt_read_announce_list_size(struct dt_torrent*);
dt_string_list dt_read_announce_list(struct dt_torrent*, size_t index);
time_t dt_read_creation_date(struct dt_torrent*);
#if defined(__cplusplus)
}
#endif

View file

@ -55,6 +55,7 @@ public:
std::string_view read_hashes() const; std::string_view read_hashes() const;
std::string_view read_created_by() const; std::string_view read_created_by() const;
std::string_view read_announce() const; std::string_view read_announce() const;
std::size_t read_announce_list_size() const;
std::vector<std::vector<std::string_view>> read_announce_list() const; std::vector<std::vector<std::string_view>> read_announce_list() const;
std::time_t read_creation_date() const; std::time_t read_creation_date() const;

View file

@ -0,0 +1,34 @@
pub_inc = include_directories('include')
should_install = not meson.is_subproject() or get_option('default_library')=='shared'
ducktorrent_target = library(meson.project_name(),
'parser.cpp',
'split.cpp',
'torrent_read.cpp',
'c_api_torrent_read.cpp',
'visitors/debug_visitor.cpp',
'visitors/find_t_visitor.cpp',
dependencies: [
boost_dep,
],
include_directories: [
pub_inc,
],
install: should_install,
)
ducktorrent_dep = declare_dependency(
include_directories: [
pub_inc,
],
link_with: ducktorrent_target,
)
if should_install
install_headers(
'include/ducktorrent/torrent_read.h',
'include/ducktorrent/torrent_read.hpp',
'include/ducktorrent/parser.hpp',
)
endif

View file

@ -19,7 +19,7 @@
//# define BOOST_SPIRIT_X3_DEBUG //# define BOOST_SPIRIT_X3_DEBUG
#endif #endif
#include "parser.hpp" #include "ducktorrent/parser.hpp"
#include <boost/spirit/home/x3.hpp> #include <boost/spirit/home/x3.hpp>
#include <boost/fusion/adapted/std_pair.hpp> #include <boost/fusion/adapted/std_pair.hpp>

View file

@ -15,8 +15,8 @@
* along with ducktorrent. If not, see <http://www.gnu.org/licenses/>. * along with ducktorrent. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "torrent_read.hpp" #include "ducktorrent/torrent_read.hpp"
#include "parser.hpp" #include "ducktorrent/parser.hpp"
#include "visitors/debug_visitor.hpp" #include "visitors/debug_visitor.hpp"
#include "visitors/find_t_visitor.hpp" #include "visitors/find_t_visitor.hpp"
#include <utility> #include <utility>
@ -231,6 +231,10 @@ std::string_view TorrentRead::read_announce() const {
return find_string("/announce", m_parsed_values); return find_string("/announce", m_parsed_values);
} }
std::size_t TorrentRead::read_announce_list_size() const {
return find_int<std::size_t>("/announce/[[size]]", m_parsed_values);
}
std::vector<std::vector<std::string_view>> TorrentRead::read_announce_list() const { std::vector<std::vector<std::string_view>> TorrentRead::read_announce_list() const {
typedef boost::spirit::x3::forward_ast<std::vector<TorrentValue>> TorrentListType; typedef boost::spirit::x3::forward_ast<std::vector<TorrentValue>> TorrentListType;

View file

@ -17,7 +17,7 @@
#pragma once #pragma once
#include "../parser.hpp" #include "ducktorrent/parser.hpp"
#include <cstddef> #include <cstddef>
#include <ostream> #include <ostream>

View file

@ -17,7 +17,7 @@
#pragma once #pragma once
#include "../parser.hpp" #include "ducktorrent/parser.hpp"
#include <string_view> #include <string_view>
#include <cstddef> #include <cstddef>
#include <boost/variant/apply_visitor.hpp> #include <boost/variant/apply_visitor.hpp>

View file

@ -1,13 +1,2 @@
executable(meson.project_name(), subdir('ducktorrent')
'main.cpp', subdir('cli')
'parser.cpp',
'split.cpp',
'torrent_read.cpp',
'visitors/debug_visitor.cpp',
'visitors/find_t_visitor.cpp',
dependencies: [
boost_dep,
libstriezel_dep,
],
install: true,
)