* Refactoring utils::Directory.

git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@1022 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
rakshasa
2007-12-23 19:12:23 +00:00
parent ccb3713a57
commit 7b053b969e
11 changed files with 126 additions and 62 deletions
+10 -12
View File
@@ -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
-1
View File
@@ -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>
+12 -3
View File
@@ -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(&not_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;
+6 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+1 -1
View File
@@ -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);
+12
View File
@@ -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
View File
@@ -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
View File
@@ -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