mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-10-11 16:49:22 +00:00
* Refactoring utils::Directory.
git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@1022 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
+10
-12
@@ -122,12 +122,12 @@ struct compare_base : public std::binary_function<_Value, _Value, bool> {
|
||||
|
||||
// Count the number of elements from the start of the containers to
|
||||
// the first inequal element.
|
||||
template <typename _InputIter>
|
||||
typename std::iterator_traits<_InputIter>::difference_type
|
||||
count_base(_InputIter __first1, _InputIter __last1,
|
||||
_InputIter __first2, _InputIter __last2) {
|
||||
template <typename _InputIter1, typename _InputIter2>
|
||||
typename std::iterator_traits<_InputIter1>::difference_type
|
||||
count_base(_InputIter1 __first1, _InputIter1 __last1,
|
||||
_InputIter2 __first2, _InputIter2 __last2) {
|
||||
|
||||
typename std::iterator_traits<_InputIter>::difference_type __n = 0;
|
||||
typename std::iterator_traits<_InputIter1>::difference_type __n = 0;
|
||||
|
||||
for ( ;__first1 != __last1 && __first2 != __last2; ++__first1, ++__first2, ++__n)
|
||||
if (*__first1 != *__first2)
|
||||
@@ -136,17 +136,17 @@ count_base(_InputIter __first1, _InputIter __last1,
|
||||
return __n;
|
||||
}
|
||||
|
||||
template <typename _InputIter>
|
||||
typename std::iterator_traits<_InputIter>::value_type
|
||||
make_base(_InputIter __first, _InputIter __last) {
|
||||
template <typename _Return, typename _InputIter, typename _Ftor>
|
||||
_Return
|
||||
make_base(_InputIter __first, _InputIter __last, _Ftor __ftor) {
|
||||
if (__first == __last)
|
||||
return "";
|
||||
|
||||
typename std::iterator_traits<_InputIter>::value_type __base = *__first++;
|
||||
_Return __base = __ftor(*__first++);
|
||||
|
||||
for ( ;__first != __last; ++__first) {
|
||||
typename std::iterator_traits<_InputIter>::difference_type __pos = count_base(__base.begin(), __base.end(),
|
||||
__first->begin(), __first->end());
|
||||
__ftor(*__first).begin(), __ftor(*__first).end());
|
||||
|
||||
if (__pos < (typename std::iterator_traits<_InputIter>::difference_type)__base.size())
|
||||
__base.resize(__pos);
|
||||
@@ -155,8 +155,6 @@ make_base(_InputIter __first, _InputIter __last) {
|
||||
return __base;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
|
||||
#include <functional>
|
||||
#include <rak/address_info.h>
|
||||
#include <rak/file_stat.h>
|
||||
#include <rak/path.h>
|
||||
#include <torrent/connection_manager.h>
|
||||
#include <torrent/dht_manager.h>
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
#include <torrent/resume.h>
|
||||
#include <torrent/object_stream.h>
|
||||
|
||||
#include "utils/directory.h"
|
||||
|
||||
#include "download.h"
|
||||
#include "download_store.h"
|
||||
|
||||
@@ -144,23 +146,30 @@ DownloadStore::remove(Download* d) {
|
||||
::unlink(create_filename(d).c_str());
|
||||
}
|
||||
|
||||
// This also needs to check that it isn't a directory.
|
||||
bool
|
||||
not_correct_format(const utils::directory_entry& entry) {
|
||||
return !DownloadStore::is_correct_format(entry.d_name);
|
||||
}
|
||||
|
||||
utils::Directory
|
||||
DownloadStore::get_formated_entries() {
|
||||
if (!is_enabled())
|
||||
return utils::Directory();
|
||||
|
||||
utils::Directory d(m_path);
|
||||
utils::Directory d;
|
||||
d.set_path(m_path);
|
||||
|
||||
if (!d.update())
|
||||
throw torrent::storage_error("core::DownloadStore::update() could not open directory \"" + m_path + "\"");
|
||||
|
||||
d.erase(std::remove_if(d.begin(), d.end(), std::not1(std::ptr_fun(&DownloadStore::is_correct_format))), d.end());
|
||||
d.erase(std::remove_if(d.begin(), d.end(), std::ptr_fun(¬_correct_format)), d.end());
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
bool
|
||||
DownloadStore::is_correct_format(std::string f) {
|
||||
DownloadStore::is_correct_format(const std::string& f) {
|
||||
if (f.size() != 48 || f.substr(40) != ".torrent")
|
||||
return false;
|
||||
|
||||
|
||||
@@ -39,9 +39,12 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "utils/directory.h"
|
||||
#include "utils/lockfile.h"
|
||||
|
||||
namespace utils {
|
||||
class Directory;
|
||||
}
|
||||
|
||||
namespace core {
|
||||
|
||||
class Download;
|
||||
@@ -63,8 +66,9 @@ public:
|
||||
// Currently shows all entries in the correct format.
|
||||
utils::Directory get_formated_entries();
|
||||
|
||||
static bool is_correct_format(const std::string& f);
|
||||
|
||||
private:
|
||||
static bool is_correct_format(std::string f);
|
||||
std::string create_filename(Download* d);
|
||||
|
||||
std::string m_path;
|
||||
|
||||
+8
-2
@@ -56,6 +56,7 @@
|
||||
#include <torrent/tracker_list.h>
|
||||
|
||||
#include "rpc/parse_commands.h"
|
||||
#include "utils/directory.h"
|
||||
|
||||
#include "globals.h"
|
||||
#include "curl_get.h"
|
||||
@@ -417,6 +418,11 @@ Manager::try_create_download(const std::string& uri, int flags, const command_li
|
||||
f->commit();
|
||||
}
|
||||
|
||||
utils::Directory
|
||||
path_expand_transform(std::string path, const utils::directory_entry& entry) {
|
||||
return path + entry.d_name;
|
||||
}
|
||||
|
||||
// Move this somewhere better.
|
||||
void
|
||||
path_expand(std::vector<std::string>* paths, const std::string& pattern) {
|
||||
@@ -454,9 +460,9 @@ path_expand(std::vector<std::string>* paths, const std::string& pattern) {
|
||||
// Only include filenames starting with '.' if the pattern
|
||||
// starts with the same.
|
||||
itr->update(r.pattern()[0] != '.');
|
||||
itr->erase(std::remove_if(itr->begin(), itr->end(), std::not1(r)), itr->end());
|
||||
itr->erase(std::remove_if(itr->begin(), itr->end(), rak::on(rak::mem_ref(&utils::directory_entry::d_name), std::not1(r))), itr->end());
|
||||
|
||||
std::transform(itr->begin(), itr->end(), std::back_inserter(nextCache), std::bind1st(std::plus<std::string>(), itr->get_path() + "/"));
|
||||
std::transform(itr->begin(), itr->end(), std::back_inserter(nextCache), rak::bind1st(std::ptr_fun(&path_expand_transform), itr->get_path() + "/"));
|
||||
}
|
||||
|
||||
currentCache.clear();
|
||||
|
||||
+21
-17
@@ -38,9 +38,12 @@
|
||||
|
||||
#include <functional>
|
||||
#include <rak/algorithm.h>
|
||||
#include <rak/file_stat.h>
|
||||
#include <rak/functional.h>
|
||||
#include <rak/path.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/dir.h>
|
||||
|
||||
#include "path_input.h"
|
||||
|
||||
namespace input {
|
||||
@@ -68,19 +71,10 @@ PathInput::pressed(int key) {
|
||||
}
|
||||
|
||||
struct _transform_filename {
|
||||
_transform_filename(const std::string& base) : m_base(base) {}
|
||||
|
||||
void operator () (std::string& filename) {
|
||||
rak::file_stat fs;
|
||||
|
||||
if (!fs.update(rak::path_expand(m_base + filename)))
|
||||
return;
|
||||
|
||||
else if (fs.is_directory())
|
||||
filename += '/';
|
||||
void operator () (utils::directory_entry& entry) {
|
||||
if (entry.d_type == DT_DIR)
|
||||
entry.d_name += '/';
|
||||
}
|
||||
|
||||
const std::string& m_base;
|
||||
};
|
||||
|
||||
void
|
||||
@@ -95,14 +89,14 @@ PathInput::receive_do_complete() {
|
||||
return;
|
||||
}
|
||||
|
||||
std::for_each(dir.begin(), dir.end(), _transform_filename(str().substr(0, dirEnd)));
|
||||
std::for_each(dir.begin(), dir.end(), _transform_filename());
|
||||
|
||||
Range r = find_incomplete(dir, str().substr(dirEnd, get_pos()));
|
||||
|
||||
if (r.first == r.second)
|
||||
return; // Show some nice colors here.
|
||||
|
||||
std::string base = rak::make_base(r.first, r.second);
|
||||
std::string base = rak::make_base<std::string>(r.first, r.second, rak::const_mem_ref(&utils::directory_entry::d_name));
|
||||
|
||||
// Clear the path after the cursor to make this code cleaner. It's
|
||||
// not really nessesary to add the complexity just because someone
|
||||
@@ -133,12 +127,22 @@ PathInput::find_last_delim() {
|
||||
return r + 1;
|
||||
}
|
||||
|
||||
inline bool
|
||||
find_complete_compare(const utils::directory_entry& complete, const std::string& base) {
|
||||
return complete.d_name.compare(0, base.size(), base);
|
||||
}
|
||||
|
||||
inline bool
|
||||
find_complete_not_compare(const utils::directory_entry& complete, const std::string& base) {
|
||||
return !complete.d_name.compare(0, base.size(), base);
|
||||
}
|
||||
|
||||
PathInput::Range
|
||||
PathInput::find_incomplete(utils::Directory& d, const std::string& f) {
|
||||
Range r;
|
||||
|
||||
r.first = std::find_if(d.begin(), d.end(), std::bind2nd(rak::compare_base<std::string>(), f));
|
||||
r.second = std::find_if(r.first, d.end(), std::not1(std::bind2nd(rak::compare_base<std::string>(), f)));
|
||||
r.first = std::find_if(d.begin(), d.end(), rak::bind2nd(std::ptr_fun(&find_complete_not_compare), f));
|
||||
r.second = std::find_if(r.first, d.end(), rak::bind2nd(std::ptr_fun(&find_complete_compare), f));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
+2
-2
@@ -101,9 +101,9 @@ parse_options(Control* c, int argc, char** argv) {
|
||||
void
|
||||
load_session_torrents(Control* c) {
|
||||
// Load session torrents.
|
||||
std::list<std::string> l = c->core()->download_store()->get_formated_entries().make_list();
|
||||
std::vector<std::string> l = c->core()->download_store()->get_formated_entries().make_list();
|
||||
|
||||
for (std::list<std::string>::iterator first = l.begin(), last = l.end(); first != last; ++first) {
|
||||
for (std::vector<std::string>::iterator first = l.begin(), last = l.end(); first != last; ++first) {
|
||||
core::DownloadFactory* f = new core::DownloadFactory(c->core());
|
||||
|
||||
// Replace with session torrent flag.
|
||||
|
||||
@@ -255,7 +255,7 @@ DownloadList::receive_view_input(Input type) {
|
||||
input->signal_show_next().connect(sigc::mem_fun(*esl, &ElementStringList::next_screen));
|
||||
|
||||
input->signal_show_range().connect(sigc::hide(sigc::hide(sigc::bind(sigc::mem_fun(*this, &DownloadList::activate_display), DISPLAY_STRING_LIST))));
|
||||
input->signal_show_range().connect(sigc::mem_fun(*esl, &ElementStringList::set_range<utils::Directory::iterator>));
|
||||
input->signal_show_range().connect(sigc::mem_fun(*esl, &ElementStringList::set_range_dirent<utils::Directory::iterator>));
|
||||
|
||||
input->bindings()['\n'] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_exit_input), type);
|
||||
input->bindings()[KEY_ENTER] = sigc::bind(sigc::mem_fun(*this, &DownloadList::receive_exit_input), type);
|
||||
|
||||
@@ -73,6 +73,18 @@ public:
|
||||
m_window->mark_dirty();
|
||||
}
|
||||
|
||||
// A hack, clean this up.
|
||||
template <typename InputIter>
|
||||
void set_range_dirent(InputIter first, InputIter last) {
|
||||
m_list.clear();
|
||||
|
||||
while (first != last)
|
||||
m_list.push_back((first++)->d_name);
|
||||
|
||||
m_window->set_range(m_list.begin(), m_list.end());
|
||||
m_window->mark_dirty();
|
||||
}
|
||||
|
||||
void next_screen();
|
||||
|
||||
private:
|
||||
|
||||
+18
-7
@@ -46,6 +46,7 @@
|
||||
|
||||
namespace utils {
|
||||
|
||||
// Keep this?
|
||||
bool
|
||||
Directory::is_valid() const {
|
||||
if (m_path.empty())
|
||||
@@ -57,6 +58,7 @@ Directory::is_valid() const {
|
||||
return d;
|
||||
}
|
||||
|
||||
// Update should take various flags and sort functors.
|
||||
bool
|
||||
Directory::update(bool hideDot) {
|
||||
if (m_path.empty())
|
||||
@@ -69,25 +71,34 @@ Directory::update(bool hideDot) {
|
||||
|
||||
struct dirent* ent;
|
||||
|
||||
// Err... let us use getdirentries here instead.
|
||||
while ((ent = readdir(d)) != NULL) {
|
||||
// Don't construct it here, check the const char.
|
||||
std::string de(ent->d_name);
|
||||
|
||||
if (!de.empty() && (!hideDot || de[0] != '.'))
|
||||
Base::push_back(ent->d_name);
|
||||
if (!de.empty() && (!hideDot || de[0] != '.')) {
|
||||
iterator itr = base_type::insert(end(), value_type());
|
||||
|
||||
itr->d_fileno = ent->d_fileno;
|
||||
itr->d_reclen = ent->d_reclen;
|
||||
itr->d_type = ent->d_type;
|
||||
itr->d_name = de;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
Base::sort(std::less<std::string>());
|
||||
std::sort(begin(), end());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Directory::Base
|
||||
std::vector<std::string>
|
||||
Directory::make_list() {
|
||||
Base l;
|
||||
std::vector<std::string> l;
|
||||
l.reserve(size());
|
||||
|
||||
for (Base::iterator itr = begin(); itr != end(); ++itr)
|
||||
l.push_back(m_path + *itr);
|
||||
for (iterator itr = begin(); itr != end(); ++itr)
|
||||
l.push_back(m_path + itr->d_name);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
+36
-15
@@ -38,28 +38,38 @@
|
||||
#define RTORRENT_UTILS_DIRECTORY_H
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
namespace utils {
|
||||
|
||||
class Directory : private std::list<std::string> {
|
||||
struct directory_entry {
|
||||
// The name and types should match POSIX.
|
||||
uint32_t d_fileno;
|
||||
uint16_t d_reclen;
|
||||
uint8_t d_type;
|
||||
|
||||
std::string d_name;
|
||||
};
|
||||
|
||||
class Directory : private std::vector<directory_entry> {
|
||||
public:
|
||||
typedef std::list<std::string> Base;
|
||||
typedef std::vector<directory_entry> base_type;
|
||||
|
||||
using Base::iterator;
|
||||
using Base::const_iterator;
|
||||
using Base::reverse_iterator;
|
||||
using Base::const_reverse_iterator;
|
||||
using base_type::iterator;
|
||||
using base_type::const_iterator;
|
||||
using base_type::reverse_iterator;
|
||||
using base_type::const_reverse_iterator;
|
||||
using base_type::value_type;
|
||||
|
||||
using Base::begin;
|
||||
using Base::end;
|
||||
using Base::rbegin;
|
||||
using Base::rend;
|
||||
using base_type::begin;
|
||||
using base_type::end;
|
||||
using base_type::rbegin;
|
||||
using base_type::rend;
|
||||
|
||||
using Base::empty;
|
||||
using Base::size;
|
||||
using base_type::empty;
|
||||
using base_type::size;
|
||||
|
||||
using Base::erase;
|
||||
using base_type::erase;
|
||||
|
||||
Directory() {}
|
||||
Directory(const std::string& path) : m_path(path) {}
|
||||
@@ -68,15 +78,26 @@ public:
|
||||
|
||||
bool update(bool hideDot = true);
|
||||
|
||||
// Ergh...
|
||||
const std::string& get_path() { return m_path; }
|
||||
void set_path(const std::string& path) { m_path = path; }
|
||||
|
||||
// Make a list with full path names.
|
||||
Base make_list();
|
||||
//
|
||||
// Fix the uses of this, real bad stuff.
|
||||
std::vector<std::string> make_list();
|
||||
|
||||
private:
|
||||
std::string m_path;
|
||||
};
|
||||
|
||||
inline bool operator == (const directory_entry& left, const directory_entry& right) { return left.d_name == right.d_name; }
|
||||
inline bool operator != (const directory_entry& left, const directory_entry& right) { return left.d_name != right.d_name; }
|
||||
inline bool operator < (const directory_entry& left, const directory_entry& right) { return left.d_name < right.d_name; }
|
||||
inline bool operator > (const directory_entry& left, const directory_entry& right) { return left.d_name > right.d_name; }
|
||||
inline bool operator <= (const directory_entry& left, const directory_entry& right) { return left.d_name <= right.d_name; }
|
||||
inline bool operator >= (const directory_entry& left, const directory_entry& right) { return left.d_name >= right.d_name; }
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user