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:
parent
b43d5ecb6a
commit
5a78ef04de
17 changed files with 355 additions and 20 deletions
|
@ -1,5 +1,5 @@
|
|||
project('ducktorrent', 'cpp',
|
||||
version: '0.2.0',
|
||||
version: '0.2.1',
|
||||
meson_version: '>=0.63.0',
|
||||
default_options: [
|
||||
'buildtype=release',
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* along with ducktorrent. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "torrent_read.hpp"
|
||||
#include "ducktorrent/torrent_read.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
9
src/cli/meson.build
Normal file
9
src/cli/meson.build
Normal file
|
@ -0,0 +1,9 @@
|
|||
executable(meson.project_name(),
|
||||
'main.cpp',
|
||||
dependencies: [
|
||||
boost_dep,
|
||||
libstriezel_dep,
|
||||
ducktorrent_dep,
|
||||
],
|
||||
install: true,
|
||||
)
|
213
src/ducktorrent/c_api_torrent_read.cpp
Normal file
213
src/ducktorrent/c_api_torrent_read.cpp
Normal 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 {};
|
||||
}
|
||||
}
|
85
src/ducktorrent/include/ducktorrent/torrent_read.h
Normal file
85
src/ducktorrent/include/ducktorrent/torrent_read.h
Normal 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
|
|
@ -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::size_t read_announce_list_size() const;
|
||||
std::vector<std::vector<std::string_view>> read_announce_list() const;
|
||||
std::time_t read_creation_date() const;
|
||||
|
34
src/ducktorrent/meson.build
Normal file
34
src/ducktorrent/meson.build
Normal 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
|
|
@ -19,7 +19,7 @@
|
|||
//# define BOOST_SPIRIT_X3_DEBUG
|
||||
#endif
|
||||
|
||||
#include "parser.hpp"
|
||||
#include "ducktorrent/parser.hpp"
|
||||
|
||||
#include <boost/spirit/home/x3.hpp>
|
||||
#include <boost/fusion/adapted/std_pair.hpp>
|
|
@ -15,8 +15,8 @@
|
|||
* along with ducktorrent. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "torrent_read.hpp"
|
||||
#include "parser.hpp"
|
||||
#include "ducktorrent/torrent_read.hpp"
|
||||
#include "ducktorrent/parser.hpp"
|
||||
#include "visitors/debug_visitor.hpp"
|
||||
#include "visitors/find_t_visitor.hpp"
|
||||
#include <utility>
|
||||
|
@ -231,6 +231,10 @@ std::string_view TorrentRead::read_announce() const {
|
|||
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 {
|
||||
typedef boost::spirit::x3::forward_ast<std::vector<TorrentValue>> TorrentListType;
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../parser.hpp"
|
||||
#include "ducktorrent/parser.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <ostream>
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../parser.hpp"
|
||||
#include "ducktorrent/parser.hpp"
|
||||
#include <string_view>
|
||||
#include <cstddef>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
|
@ -1,13 +1,2 @@
|
|||
executable(meson.project_name(),
|
||||
'main.cpp',
|
||||
'parser.cpp',
|
||||
'split.cpp',
|
||||
'torrent_read.cpp',
|
||||
'visitors/debug_visitor.cpp',
|
||||
'visitors/find_t_visitor.cpp',
|
||||
dependencies: [
|
||||
boost_dep,
|
||||
libstriezel_dep,
|
||||
],
|
||||
install: true,
|
||||
)
|
||||
subdir('ducktorrent')
|
||||
subdir('cli')
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue