diff --git a/trunk/src/clusterization.h b/trunk/src/clusterization.h index 183faab..b613fdb 100644 --- a/trunk/src/clusterization.h +++ b/trunk/src/clusterization.h @@ -16,7 +16,8 @@ class clusterization: public category::kleisli::arr, boost: } }; typedef boost::shared_ptr > Cont; - std::map _continuations; + typedef std::map map; + map _continuations; public: void next(const T_ptr& t) { typename std::map::iterator it = _continuations.find(t); @@ -28,6 +29,12 @@ class clusterization: public category::kleisli::arr, boost: it->second->next(t); } } + void stop() { + for (typename map::iterator it = _continuations.begin(); it != _continuations.end(); ++it) { + it->second->stop(); + } + _continuations.clear(); + } }; #endif diff --git a/trunk/src/comparator.h b/trunk/src/comparator.h new file mode 100644 index 0000000..629b13f --- /dev/null +++ b/trunk/src/comparator.h @@ -0,0 +1,43 @@ +#ifndef _COMPARATOR_H_ +#define _COMPARATOR_H_ + +#include +#include + +#include "kleisli.h" +#include "type_list.h" + +template +class comparator: public category::kleisli::arr, boost::shared_ptr > { + typedef boost::shared_ptr T_ptr; + typedef boost::shared_ptr C_ptr; + typedef boost::shared_ptr< category::kleisli::end > Cont; + typedef std::vector< std::pair > vector; + vector _values; +public: + void next(const T_ptr& t) { + for (typename vector::iterator it = _values.begin(); it != _values.end(); ++it) { + C_ptr r = it->first->compare(t); + if (r) { + it->second->next(r); + return; + } + } + Cont cont = category::kleisli::sink::continuation().clone(); + if (SUPER_SUB_CLASS(C, T)) { + cont->next(t); + } + _values.push_back(std::make_pair(t, cont)); + } + void stop() { + for (typename vector::iterator it = _values.begin(); it != _values.end(); ++it) { + it->second->stop(); + } + _values.clear(); + } + boost::shared_ptr< category::kleisli::end > clone() const { + return boost::make_shared< comparator >(*this); + } +}; + +#endif diff --git a/trunk/src/default_main.cpp b/trunk/src/default_main.cpp index cd066f3..3cd71c3 100644 --- a/trunk/src/default_main.cpp +++ b/trunk/src/default_main.cpp @@ -1,5 +1,4 @@ -#include - +#include "comparator.h" #include "clusterization.h" #include "program_options.h" #include "filesystem.h" @@ -22,28 +21,36 @@ class elem_filter: public arr { }; template -class comparator: public category::kleisli::arr, file_type::compare_result> { +class accumulator: public arr, boost::shared_ptr > { std::vector< boost::shared_ptr > _values; public: void next(const boost::shared_ptr& t) { - typedef typename std::vector >::iterator iterator; - for (iterator it = _values.begin(); it != _values.end(); ++it) { - (*it)->compare(*t, sink::continuation()); - } _values.push_back(t); } + void stop() { + if (_values.size() > 1) { + make_pair(_values.begin(), _values.end()) + >>= sink< boost::shared_ptr >::continuation(); + } + _values.clear(); + } boost::shared_ptr< end< boost::shared_ptr > > clone() const { - return boost::make_shared< comparator >(*this); + return boost::make_shared< accumulator >(*this); } }; void default_main(const program_options& po) { + struct : end< boost::shared_ptr > { + void next(const boost::shared_ptr& t) { std::cout << t->path() << "\n"; } + void stop() { std::cout << "\n"; } + } output; + make_pair(po.input_files().begin(), po.input_files().end()) - >>= The() + >>= fs::recursive() >>= (po.extensions().empty() ? The< arr >() : The(po.extensions())) - >>= The() + >>= file_typer_match_first() >>= clusterization() - >>= The >() - >>= The - (std::ostream_iterator(std::cout, "\n")); + >>= comparator() + >>= accumulator() + >>= output; } diff --git a/trunk/src/file_types/base.cpp b/trunk/src/file_types/base.cpp index 3af6390..514678c 100644 --- a/trunk/src/file_types/base.cpp +++ b/trunk/src/file_types/base.cpp @@ -13,29 +13,23 @@ boost::shared_ptr base::try_file(const fs::path& file) { return boost::make_shared(file); } -void base::compare(const base& a, category::kleisli::end& cont) const { - if (fs::file_size(_path) != fs::file_size(a._path)) { - return; +boost::shared_ptr base::compare(const boost::shared_ptr& a) const { + if (fs::file_size(_path) != fs::file_size(a->_path)) { + return boost::shared_ptr(); } const int buf_size = 4096; char buf1[buf_size], buf2[buf_size]; - fs::ifstream file1(_path), file2(a._path); + fs::ifstream file1(_path), file2(a->_path); while (true) { file1.read(buf1, buf_size); file2.read(buf2, buf_size); if (file1.gcount() != file2.gcount() || file1.eof() != file2.eof() || memcmp(buf1, buf2, file1.gcount()) != 0) { - return; + return boost::shared_ptr(); } if (file1.eof() && file2.eof()) { - cont.next(compare_result(_path, a._path)); - return; + return a; } } } -std::ostream& operator<<(std::ostream& o, const compare_result& r) { - o << "files " << r.file1() << " and " << r.file2() << " are equal"; - return o; -} - } diff --git a/trunk/src/file_types/base.h b/trunk/src/file_types/base.h index c440dd8..cbe563a 100644 --- a/trunk/src/file_types/base.h +++ b/trunk/src/file_types/base.h @@ -2,6 +2,7 @@ #define _FILE_TYPE_BASE_H_ #include +#include #include "../filesystem.h" #include "../type_list.h" @@ -9,24 +10,13 @@ namespace file_type { -class compare_result { - const fs::path& _file1; - const fs::path& _file2; -public: - compare_result(const fs::path& f1, const fs::path& f2): _file1(f1), _file2(f2) {} - const fs::path& file1() const { return _file1; } - const fs::path& file2() const { return _file2; } -}; - -std::ostream& operator<<(std::ostream& o, const compare_result& r); - class base { fs::path _path; public: base(const fs::path& p): _path(p) {} const fs::path& path() const { return _path; } static boost::shared_ptr try_file(const fs::path& file); - virtual void compare(const base& a, category::kleisli::end& cont) const; + virtual boost::shared_ptr compare(const boost::shared_ptr& a) const; }; } diff --git a/trunk/src/file_types/text.cpp b/trunk/src/file_types/text.cpp index 746e15f..6992356 100644 --- a/trunk/src/file_types/text.cpp +++ b/trunk/src/file_types/text.cpp @@ -15,11 +15,11 @@ boost::shared_ptr text::try_file(const boost::shared_ptr& file) { return boost::shared_ptr(); } -void text::compare(const base& a, category::kleisli::end& cont) const { - if (fs::file_size(path()) != fs::file_size(a.path())) { - return; +boost::shared_ptr text::compare(const boost::shared_ptr& a) const { + if (fs::file_size(path()) != fs::file_size(a->path())) { + return boost::shared_ptr(); } - cont.next(compare_result(path(), a.path())); + return a; } } diff --git a/trunk/src/file_types/text.h b/trunk/src/file_types/text.h index a07ec13..44d2ed6 100644 --- a/trunk/src/file_types/text.h +++ b/trunk/src/file_types/text.h @@ -9,7 +9,7 @@ namespace file_type { struct text: base { text(const fs::path& p): base(p) {} static boost::shared_ptr try_file(const boost::shared_ptr& file); - void compare(const base& a, category::kleisli::end& cont) const; + boost::shared_ptr compare(const boost::shared_ptr& a) const; }; } diff --git a/trunk/src/kleisli.h b/trunk/src/kleisli.h index f4c1929..69dd253 100644 --- a/trunk/src/kleisli.h +++ b/trunk/src/kleisli.h @@ -16,23 +16,27 @@ template class R, typename S, typen template struct end { virtual void next(const S&) = 0; + virtual void stop() = 0; virtual boost::shared_ptr< end > clone() const { return boost::shared_ptr< end >(); } }; template struct empty: end { void next(const S&) {} + void stop() {} boost::shared_ptr< end > clone() const { return boost::make_shared< empty >(); } }; template void operator>>=(const V& from, end& to) { to.next(from); + to.stop(); } template void operator>>=(const std::pair& from, end& to) { for (Iter it = from.first; it != from.second; to.next(*it++)) ; + to.stop(); } template @@ -40,6 +44,7 @@ void operator>>=(const std::pair& from, end& to) { for (int i = 0; i < from.second; ++i) { to.next(from.first()); } + to.stop(); } template @@ -50,16 +55,13 @@ class sink { void set_continuation(end& c) { _continuation = &c; } public: sink(): _continuation(&The< empty >()) {} - void pass(const T& t) { - _continuation->next(t); - } + void pass(const T& t) { _continuation->next(t); } }; template struct arr: sink, end { - void next(const T& t) { - pass(t); - } + void next(const T& t) { pass(t); } + void stop() { sink::continuation().stop(); } end& operator>>=(end& to) { set_continuation(to); return *this; @@ -72,6 +74,7 @@ class iterator_end: public end { public: iterator_end(const Iter& i): it(i) {} void next(const V& value) { *it++ = value; } + void stop() {} boost::shared_ptr< end > clone() const { return boost::make_shared< iterator_end >(it); } };