diff --git a/rak/algorithm.h b/rak/algorithm.h index 4580409f..3dfa9f36 100644 --- a/rak/algorithm.h +++ b/rak/algorithm.h @@ -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 std::iterator_traits<_InputIter>::difference_type -count_base(_InputIter __first1, _InputIter __last1, - _InputIter __first2, _InputIter __last2) { +template +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 std::iterator_traits<_InputIter>::value_type -make_base(_InputIter __first, _InputIter __last) { +template +_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 diff --git a/src/command_network.cc b/src/command_network.cc index 0e238cb2..c932dbab 100644 --- a/src/command_network.cc +++ b/src/command_network.cc @@ -38,7 +38,6 @@ #include #include -#include #include #include #include diff --git a/src/core/download_store.cc b/src/core/download_store.cc index de31cc6a..d1b366f4 100644 --- a/src/core/download_store.cc +++ b/src/core/download_store.cc @@ -51,6 +51,8 @@ #include #include +#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; diff --git a/src/core/download_store.h b/src/core/download_store.h index a2c2dae7..42bd76a5 100644 --- a/src/core/download_store.h +++ b/src/core/download_store.h @@ -39,9 +39,12 @@ #include -#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; diff --git a/src/core/manager.cc b/src/core/manager.cc index c84b4047..1e6d60dc 100644 --- a/src/core/manager.cc +++ b/src/core/manager.cc @@ -56,6 +56,7 @@ #include #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* paths, const std::string& pattern) { @@ -454,9 +460,9 @@ path_expand(std::vector* 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(), 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(); diff --git a/src/input/path_input.cc b/src/input/path_input.cc index 76cd0719..1422bb7e 100644 --- a/src/input/path_input.cc +++ b/src/input/path_input.cc @@ -38,9 +38,12 @@ #include #include -#include +#include #include +#include +#include + #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(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(), f)); - r.second = std::find_if(r.first, d.end(), std::not1(std::bind2nd(rak::compare_base(), 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; } diff --git a/src/main.cc b/src/main.cc index b8c17abf..5acfce32 100644 --- a/src/main.cc +++ b/src/main.cc @@ -101,9 +101,9 @@ parse_options(Control* c, int argc, char** argv) { void load_session_torrents(Control* c) { // Load session torrents. - std::list l = c->core()->download_store()->get_formated_entries().make_list(); + std::vector l = c->core()->download_store()->get_formated_entries().make_list(); - for (std::list::iterator first = l.begin(), last = l.end(); first != last; ++first) { + for (std::vector::iterator first = l.begin(), last = l.end(); first != last; ++first) { core::DownloadFactory* f = new core::DownloadFactory(c->core()); // Replace with session torrent flag. diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc index 39c7cda8..8ec98d16 100644 --- a/src/ui/download_list.cc +++ b/src/ui/download_list.cc @@ -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)); + input->signal_show_range().connect(sigc::mem_fun(*esl, &ElementStringList::set_range_dirent)); 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); diff --git a/src/ui/element_string_list.h b/src/ui/element_string_list.h index 1698e5f9..82b1e4a0 100644 --- a/src/ui/element_string_list.h +++ b/src/ui/element_string_list.h @@ -73,6 +73,18 @@ public: m_window->mark_dirty(); } + // A hack, clean this up. + template + 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: diff --git a/src/utils/directory.cc b/src/utils/directory.cc index 5ba08ff1..fc53a318 100644 --- a/src/utils/directory.cc +++ b/src/utils/directory.cc @@ -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::sort(begin(), end()); return true; } -Directory::Base +std::vector Directory::make_list() { - Base l; + std::vector 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; } diff --git a/src/utils/directory.h b/src/utils/directory.h index eb755572..4a0057a8 100644 --- a/src/utils/directory.h +++ b/src/utils/directory.h @@ -38,28 +38,38 @@ #define RTORRENT_UTILS_DIRECTORY_H #include -#include +#include namespace utils { -class Directory : private std::list { +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 { public: - typedef std::list Base; + typedef std::vector 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 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