update examples to use C++11 and more succinct error handling

This commit is contained in:
arvidn 2017-12-30 20:33:00 +01:00 committed by Arvid Norberg
parent 672556b4b2
commit 4c5ef920f0
3 changed files with 102 additions and 116 deletions

View File

@ -45,14 +45,13 @@ POSSIBILITY OF SUCH DAMAGE.
std::vector<char> load_file(std::string const& filename) std::vector<char> load_file(std::string const& filename)
{ {
std::vector<char> ret;
std::fstream in; std::fstream in;
in.exceptions(std::ifstream::failbit); in.exceptions(std::ifstream::failbit);
in.open(filename.c_str(), std::ios_base::in | std::ios_base::binary); in.open(filename.c_str(), std::ios_base::in | std::ios_base::binary);
in.seekg(0, std::ios_base::end); in.seekg(0, std::ios_base::end);
auto const size = in.tellg(); size_t const size = size_t(in.tellg());
in.seekg(0, std::ios_base::beg); in.seekg(0, std::ios_base::beg);
ret.resize(static_cast<std::size_t>(size)); std::vector<char> ret(size);
in.read(ret.data(), ret.size()); in.read(ret.data(), ret.size());
return ret; return ret;
} }
@ -60,7 +59,7 @@ std::vector<char> load_file(std::string const& filename)
int main(int argc, char* argv[]) try int main(int argc, char* argv[]) try
{ {
if (argc < 2 || argc > 4) { if (argc < 2 || argc > 4) {
fputs("usage: dump_torrent torrent-file [total-items-limit] [recursion-limit]\n", stderr); std::cerr << "usage: dump_torrent torrent-file [total-items-limit] [recursion-limit]\n";
return 1; return 1;
} }
@ -120,10 +119,10 @@ int main(int argc, char* argv[]) try
, t.name().c_str() , t.name().c_str()
, t.num_files()); , t.num_files());
lt::file_storage const& st = t.files(); lt::file_storage const& st = t.files();
for (lt::file_index_t i(0); i < lt::file_index_t(st.num_files()); ++i) for (lt::file_index_t i(0); i < st.end_file(); ++i)
{ {
lt::piece_index_t const first = st.map_file(i, 0, 0).piece; auto const first = st.map_file(i, 0, 0).piece;
lt::piece_index_t const last = st.map_file(i, (std::max)(std::int64_t(st.file_size(i))-1, std::int64_t(0)), 0).piece; auto const last = st.map_file(i, (std::max)(std::int64_t(st.file_size(i))-1, std::int64_t(0)), 0).piece;
auto const flags = st.file_flags(i); auto const flags = st.file_flags(i);
std::stringstream file_hash; std::stringstream file_hash;
if (!st.hash(i).is_all_zeros()) if (!st.hash(i).is_all_zeros())

View File

@ -52,14 +52,13 @@ using namespace std::placeholders;
std::vector<char> load_file(std::string const& filename) std::vector<char> load_file(std::string const& filename)
{ {
std::vector<char> ret;
std::fstream in; std::fstream in;
in.exceptions(std::ifstream::failbit); in.exceptions(std::ifstream::failbit);
in.open(filename.c_str(), std::ios_base::in | std::ios_base::binary); in.open(filename.c_str(), std::ios_base::in | std::ios_base::binary);
in.seekg(0, std::ios_base::end); in.seekg(0, std::ios_base::end);
size_t const size = size_t(in.tellg()); size_t const size = size_t(in.tellg());
in.seekg(0, std::ios_base::beg); in.seekg(0, std::ios_base::beg);
ret.resize(size); std::vector<char> ret(size);
in.read(ret.data(), ret.size()); in.read(ret.data(), ret.size());
return ret; return ret;
} }
@ -76,8 +75,7 @@ std::string branch_path(std::string const& f)
int len = int(f.size()); int len = int(f.size());
// if the last character is / or \ ignore it // if the last character is / or \ ignore it
if (f[len-1] == '/' || f[len-1] == '\\') --len; if (f[len-1] == '/' || f[len-1] == '\\') --len;
while (len > 0) while (len > 0) {
{
--len; --len;
if (f[len] == '/' || f[len] == '\\') if (f[len] == '/' || f[len] == '\\')
break; break;
@ -108,63 +106,61 @@ bool file_filter(std::string const& f)
// return false if the first character of the filename is a . // return false if the first character of the filename is a .
if (sep[0] == '.') return false; if (sep[0] == '.') return false;
std::fprintf(stderr, "%s\n", f.c_str()); std::cerr << f << "\n";
return true; return true;
} }
void print_progress(lt::piece_index_t i, int num)
{
std::fprintf(stderr, "\r%d/%d", static_cast<int>(i)+1, num);
}
void print_usage() void print_usage()
{ {
fputs("usage: make_torrent FILE [OPTIONS]\n" std::cerr << R"(usage: make_torrent FILE [OPTIONS]
"\n"
"Generates a torrent file from the specified file\n" Generates a torrent file from the specified file
"or directory and writes it to standard out\n\n" or directory and writes it to standard out
"OPTIONS:\n"
"-m file generate a merkle hash tree torrent.\n"
" merkle torrents require client support\n" OPTIONS:
" the resulting full merkle tree is written to\n" -m file generate a merkle hash tree torrent.
" the specified file\n" merkle torrents require client support
"-w url adds a web seed to the torrent with\n" the resulting full merkle tree is written to
" the specified url\n" the specified file
"-t url adds the specified tracker to the\n" -w url adds a web seed to the torrent with
" torrent. For multiple trackers, specify more\n" the specified url
" -t options\n" -t url adds the specified tracker to the
"-c comment sets the comment to the specified string\n" torrent. For multiple trackers, specify more
"-C creator sets the created-by field to the specified string\n" -t options
"-p bytes enables padding files. Files larger\n" -c comment sets the comment to the specified string
" than bytes will be piece-aligned\n" -C creator sets the created-by field to the specified string
"-s bytes specifies a piece size for the torrent\n" -p bytes enables padding files. Files larger
" This has to be a multiple of 16 kiB\n" than bytes will be piece-aligned
"-l Don't follow symlinks, instead encode them as\n" -s bytes specifies a piece size for the torrent
" links in the torrent file\n" This has to be a multiple of 16 kiB
"-o file specifies the output filename of the torrent file\n" -l Don't follow symlinks, instead encode them as
" If this is not specified, the torrent file is\n" links in the torrent file
" printed to the standard out, except on windows\n" -o file specifies the output filename of the torrent file
" where the filename defaults to a.torrent\n" If this is not specified, the torrent file is
"-r file add root certificate to the torrent, to verify\n" printed to the standard out, except on windows
" the HTTPS tracker\n" where the filename defaults to a.torrent
"-S info-hash add a similar torrent by info-hash. The similar\n" -r file add root certificate to the torrent, to verify
" torrent is expected to share some files with this one\n" the HTTPS tracker
"-L collection add a collection name to this torrent. Other torrents\n" -S info-hash add a similar torrent by info-hash. The similar
" in the same collection is expected to share files\n" torrent is expected to share some files with this one
" with this one.\n" -L collection add a collection name to this torrent. Other torrents
"-M make the torrent compatible with mutable torrents\n" in the same collection is expected to share files
" this means aligning large files and pad them in order\n" with this one.
" for piece hashes to uniquely indentify a file without\n" -M make the torrent compatible with mutable torrents
" overlap\n" this means aligning large files and pad them in order
, stderr); for piece hashes to uniquely indentify a file without
overlap
)";
} }
int main(int argc, char* argv[]) try int main(int argc_, char const* argv_[]) try
{ {
lt::span<char const*> args(argv_, size_t(argc_));
std::string creator_str = "libtorrent"; std::string creator_str = "libtorrent";
std::string comment_str; std::string comment_str;
if (argc < 2) { if (args.size() < 2) {
print_usage(); print_usage();
return 1; return 1;
} }
@ -186,17 +182,16 @@ int main(int argc, char* argv[]) try
outfile = "a.torrent"; outfile = "a.torrent";
#endif #endif
std::string full_path = argv[1]; std::string full_path = args[1];
argv += 2; args = args.subspan(2);
argc -= 2;
for (; argc > 0; --argc, ++argv) { for (; !args.empty(); args = args.subspan(1)) {
if (argv[0][0] != '-') { if (args[0][0] != '-') {
print_usage(); print_usage();
return 1; return 1;
} }
char const flag = argv[0][1]; char const flag = args[0][1];
switch (flag) switch (flag)
{ {
@ -209,41 +204,41 @@ int main(int argc, char* argv[]) try
continue; continue;
} }
if (argc < 2) { if (args.size() < 2) {
print_usage(); print_usage();
return 1; return 1;
} }
switch (flag) switch (flag)
{ {
case 'w': web_seeds.push_back(argv[1]); break; case 'w': web_seeds.push_back(args[1]); break;
case 't': trackers.push_back(argv[1]); break; case 't': trackers.push_back(args[1]); break;
case 's': piece_size = atoi(argv[1]); break; case 's': piece_size = atoi(args[1]); break;
case 'o': outfile = argv[1]; break; case 'o': outfile = args[1]; break;
case 'C': creator_str = argv[1]; break; case 'C': creator_str = args[1]; break;
case 'c': comment_str = argv[1]; break; case 'c': comment_str = args[1]; break;
case 'r': root_cert = argv[1]; break; case 'r': root_cert = args[1]; break;
case 'L': collections.push_back(argv[1]); break; case 'L': collections.push_back(args[1]); break;
case 'p': case 'p':
pad_file_limit = atoi(argv[1]); pad_file_limit = atoi(args[1]);
flags |= lt::create_torrent::optimize_alignment; flags |= lt::create_torrent::optimize_alignment;
break; break;
case 'm': case 'm':
merklefile = argv[1]; merklefile = args[1];
flags |= lt::create_torrent::merkle; flags |= lt::create_torrent::merkle;
break; break;
case 'S': { case 'S': {
if (strlen(argv[1]) != 40) { if (strlen(args[1]) != 40) {
std::fprintf(stderr, "invalid info-hash for -S. " std::cerr << "invalid info-hash for -S. "
"Expected 40 hex characters\n"); "Expected 40 hex characters\n";
print_usage(); print_usage();
return 1; return 1;
} }
std::stringstream hash(argv[1]); std::stringstream hash(args[1]);
lt::sha1_hash ih; lt::sha1_hash ih;
hash >> ih; hash >> ih;
if (hash.fail()) { if (hash.fail()) {
std::fprintf(stderr, "invalid info-hash for -S\n"); std::cerr << "invalid info-hash for -S\n";
print_usage(); print_usage();
return 1; return 1;
} }
@ -254,8 +249,7 @@ int main(int argc, char* argv[]) try
print_usage(); print_usage();
return 1; return 1;
} }
++argv; args = args.subspan(1);
--argc;
} }
lt::file_storage fs; lt::file_storage fs;
@ -271,10 +265,9 @@ int main(int argc, char* argv[]) try
full_path = cwd + ("\\" + full_path); full_path = cwd + ("\\" + full_path);
#else #else
char const* ret = getcwd(cwd, sizeof(cwd)); char const* ret = getcwd(cwd, sizeof(cwd));
if (ret == NULL) if (ret == nullptr) {
{ std::cerr << "failed to get current working directory: "
std::fprintf(stderr, "failed to get current working directory: %s\n" << strerror(errno) << "\n";
, strerror(errno));
return 1; return 1;
} }
full_path = cwd + ("/" + full_path); full_path = cwd + ("/" + full_path);
@ -289,30 +282,26 @@ int main(int argc, char* argv[]) try
lt::create_torrent t(fs, piece_size, pad_file_limit, flags); lt::create_torrent t(fs, piece_size, pad_file_limit, flags);
int tier = 0; int tier = 0;
for (std::vector<std::string>::iterator i = trackers.begin() for (std::string const& tr : trackers) {
, end(trackers.end()); i != end; ++i, ++tier) t.add_tracker(tr, tier);
t.add_tracker(*i, tier); ++tier;
for (std::vector<std::string>::iterator i = web_seeds.begin()
, end(web_seeds.end()); i != end; ++i)
t.add_url_seed(*i);
for (std::vector<std::string>::iterator i = collections.begin()
, end(collections.end()); i != end; ++i)
t.add_collection(*i);
for (std::vector<lt::sha1_hash>::iterator i = similar.begin()
, end(similar.end()); i != end; ++i)
t.add_similar_torrent(*i);
lt::error_code ec;
set_piece_hashes(t, branch_path(full_path)
, std::bind(&print_progress, _1, t.num_pieces()), ec);
if (ec) {
std::cerr << ec.message() << "\n";
return 1;
} }
for (std::string const& ws : web_seeds)
t.add_url_seed(ws);
for (std::string const& c : collections)
t.add_collection(c);
for (lt::sha1_hash const& s : similar)
t.add_similar_torrent(s);
auto const num = t.num_pieces();
lt::set_piece_hashes(t, branch_path(full_path)
, [num] (lt::piece_index_t const p) {
std::cerr << "\r" << p << "/" << num;
});
std::cerr << "\n"; std::cerr << "\n";
t.set_creator(creator_str.c_str()); t.set_creator(creator_str.c_str());
if (!comment_str.empty()) { if (!comment_str.empty()) {
@ -331,17 +320,18 @@ int main(int argc, char* argv[]) try
std::fstream out; std::fstream out;
out.exceptions(std::ifstream::failbit); out.exceptions(std::ifstream::failbit);
out.open(outfile.c_str(), std::ios_base::out | std::ios_base::binary); out.open(outfile.c_str(), std::ios_base::out | std::ios_base::binary);
out.write(&torrent[0], torrent.size()); out.write(torrent.data(), torrent.size());
} }
else { else {
std::cout.write(&torrent[0], torrent.size()); std::cout.write(torrent.data(), torrent.size());
} }
if (!merklefile.empty()) { if (!merklefile.empty()) {
std::fstream merkle; std::fstream merkle;
merkle.exceptions(std::ifstream::failbit); merkle.exceptions(std::ifstream::failbit);
merkle.open(merklefile.c_str(), std::ios_base::out | std::ios_base::binary); merkle.open(merklefile.c_str(), std::ios_base::out | std::ios_base::binary);
merkle.write(reinterpret_cast<char const*>(&t.merkle_tree()[0]), t.merkle_tree().size() * 20); auto const& tree = t.merkle_tree();
merkle.write(reinterpret_cast<char const*>(tree.data()), tree.size() * 20);
} }
return 0; return 0;
} }

View File

@ -40,8 +40,7 @@ POSSIBILITY OF SUCH DAMAGE.
int main(int argc, char* argv[]) try int main(int argc, char* argv[]) try
{ {
if (argc != 2) if (argc != 2) {
{
std::cerr << "usage: ./simple_client torrent-file\n" std::cerr << "usage: ./simple_client torrent-file\n"
"to stop the client, press return.\n"; "to stop the client, press return.\n";
return 1; return 1;
@ -50,7 +49,7 @@ int main(int argc, char* argv[]) try
lt::session s; lt::session s;
lt::add_torrent_params p; lt::add_torrent_params p;
p.save_path = "./"; p.save_path = "./";
p.ti = std::make_shared<lt::torrent_info>(std::string(argv[1])); p.ti = std::make_shared<lt::torrent_info>(argv[1]);
s.add_torrent(p); s.add_torrent(p);
// wait for the user to end // wait for the user to end
@ -59,8 +58,6 @@ int main(int argc, char* argv[]) try
(void)ret; // ignore (void)ret; // ignore
return 0; return 0;
} }
catch (std::exception const& e) catch (std::exception const& e) {
{
std::cerr << "ERROR: " << e.what() << "\n"; std::cerr << "ERROR: " << e.what() << "\n";
} }