Skip to content

Commit

Permalink
grouping comparator added
Browse files Browse the repository at this point in the history
git-svn-id: https://projectname.googlecode.com/svn/trunk@10 c416075f-80b4-e980-4839-00ea3ed24e77
  • Loading branch information
valery.isaev@gmail.com committed Mar 22, 2011
1 parent a397a36 commit e752bc4
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 49 deletions.
9 changes: 8 additions & 1 deletion trunk/src/clusterization.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ class clusterization: public category::kleisli::arr<boost::shared_ptr<T>, boost:
}
};
typedef boost::shared_ptr<category::kleisli::end<T_ptr> > Cont;
std::map<T_ptr, Cont, less> _continuations;
typedef std::map<T_ptr, Cont, less> map;
map _continuations;
public:
void next(const T_ptr& t) {
typename std::map<T_ptr, Cont, less>::iterator it = _continuations.find(t);
Expand All @@ -28,6 +29,12 @@ class clusterization: public category::kleisli::arr<boost::shared_ptr<T>, boost:
it->second->next(t);
}
}
void stop() {
for (typename map::iterator it = _continuations.begin(); it != _continuations.end(); ++it) {
it->second->stop();
}
_continuations.clear();
}
};

#endif
43 changes: 43 additions & 0 deletions trunk/src/comparator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#ifndef _COMPARATOR_H_
#define _COMPARATOR_H_

#include <boost/shared_ptr.hpp>
#include <vector>

#include "kleisli.h"
#include "type_list.h"

template<typename T, typename C>
class comparator: public category::kleisli::arr<boost::shared_ptr<T>, boost::shared_ptr<C> > {
typedef boost::shared_ptr<T> T_ptr;
typedef boost::shared_ptr<C> C_ptr;
typedef boost::shared_ptr< category::kleisli::end<C_ptr> > Cont;
typedef std::vector< std::pair<T_ptr, Cont> > 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<C_ptr>::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<T_ptr> > clone() const {
return boost::make_shared< comparator<T, C> >(*this);
}
};

#endif
33 changes: 20 additions & 13 deletions trunk/src/default_main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include <boost/shared_ptr.hpp>

#include "comparator.h"
#include "clusterization.h"
#include "program_options.h"
#include "filesystem.h"
Expand All @@ -22,28 +21,36 @@ class elem_filter: public arr<fs::path, fs::path> {
};

template<typename T>
class comparator: public category::kleisli::arr<boost::shared_ptr<T>, file_type::compare_result> {
class accumulator: public arr<boost::shared_ptr<T>, boost::shared_ptr<T> > {
std::vector< boost::shared_ptr<T> > _values;
public:
void next(const boost::shared_ptr<T>& t) {
typedef typename std::vector<boost::shared_ptr<T> >::iterator iterator;
for (iterator it = _values.begin(); it != _values.end(); ++it) {
(*it)->compare(*t, sink<file_type::compare_result>::continuation());
}
_values.push_back(t);
}
void stop() {
if (_values.size() > 1) {
make_pair(_values.begin(), _values.end())
>>= sink< boost::shared_ptr<T> >::continuation();
}
_values.clear();
}
boost::shared_ptr< end< boost::shared_ptr<T> > > clone() const {
return boost::make_shared< comparator<T> >(*this);
return boost::make_shared< accumulator<T> >(*this);
}
};

void default_main(const program_options& po) {
struct : end< boost::shared_ptr<file_type::base> > {
void next(const boost::shared_ptr<file_type::base>& 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>()
>>= fs::recursive()
>>= (po.extensions().empty() ? The< arr<fs::path, fs::path> >() : The<elem_filter>(po.extensions()))
>>= The<file_typer_match_first>()
>>= file_typer_match_first()
>>= clusterization<file_type::base>()
>>= The<comparator<file_type::base> >()
>>= The<iterator_end, file_type::compare_result>
(std::ostream_iterator<file_type::compare_result>(std::cout, "\n"));
>>= comparator<file_type::base, file_type::base>()
>>= accumulator<file_type::base>()
>>= output;
}
18 changes: 6 additions & 12 deletions trunk/src/file_types/base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,23 @@ boost::shared_ptr<base> base::try_file(const fs::path& file) {
return boost::make_shared<base>(file);
}

void base::compare(const base& a, category::kleisli::end<compare_result>& cont) const {
if (fs::file_size(_path) != fs::file_size(a._path)) {
return;
boost::shared_ptr<base> base::compare(const boost::shared_ptr<base>& a) const {
if (fs::file_size(_path) != fs::file_size(a->_path)) {
return boost::shared_ptr<base>();
}
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<base>();
}
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;
}

}
14 changes: 2 additions & 12 deletions trunk/src/file_types/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,21 @@
#define _FILE_TYPE_BASE_H_

#include <boost/shared_ptr.hpp>
#include <vector>

#include "../filesystem.h"
#include "../type_list.h"
#include "../kleisli.h"

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<base> try_file(const fs::path& file);
virtual void compare(const base& a, category::kleisli::end<compare_result>& cont) const;
virtual boost::shared_ptr<base> compare(const boost::shared_ptr<base>& a) const;
};

}
Expand Down
8 changes: 4 additions & 4 deletions trunk/src/file_types/text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ boost::shared_ptr<text> text::try_file(const boost::shared_ptr<base>& file) {
return boost::shared_ptr<text>();
}

void text::compare(const base& a, category::kleisli::end<compare_result>& cont) const {
if (fs::file_size(path()) != fs::file_size(a.path())) {
return;
boost::shared_ptr<base> text::compare(const boost::shared_ptr<base>& a) const {
if (fs::file_size(path()) != fs::file_size(a->path())) {
return boost::shared_ptr<base>();
}
cont.next(compare_result(path(), a.path()));
return a;
}

}
2 changes: 1 addition & 1 deletion trunk/src/file_types/text.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace file_type {
struct text: base {
text(const fs::path& p): base(p) {}
static boost::shared_ptr<text> try_file(const boost::shared_ptr<base>& file);
void compare(const base& a, category::kleisli::end<compare_result>& cont) const;
boost::shared_ptr<base> compare(const boost::shared_ptr<base>& a) const;
};

}
Expand Down
15 changes: 9 additions & 6 deletions trunk/src/kleisli.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,35 @@ template<template<typename S, typename T, typename U> class R, typename S, typen
template<typename S>
struct end {
virtual void next(const S&) = 0;
virtual void stop() = 0;
virtual boost::shared_ptr< end<S> > clone() const { return boost::shared_ptr< end<S> >(); }
};

template<typename S>
struct empty: end<S> {
void next(const S&) {}
void stop() {}
boost::shared_ptr< end<S> > clone() const { return boost::make_shared< empty<S> >(); }
};

template<typename V>
void operator>>=(const V& from, end<V>& to) {
to.next(from);
to.stop();
}

template<typename Iter, typename V>
void operator>>=(const std::pair<Iter, Iter>& from, end<V>& to) {
for (Iter it = from.first; it != from.second; to.next(*it++)) ;
to.stop();
}

template<typename Funct, typename V>
void operator>>=(const std::pair<Funct, int>& from, end<V>& to) {
for (int i = 0; i < from.second; ++i) {
to.next(from.first());
}
to.stop();
}

template<typename T>
Expand All @@ -50,16 +55,13 @@ class sink {
void set_continuation(end<T>& c) { _continuation = &c; }
public:
sink(): _continuation(&The< empty<T> >()) {}
void pass(const T& t) {
_continuation->next(t);
}
void pass(const T& t) { _continuation->next(t); }
};

template<typename S, typename T>
struct arr: sink<T>, end<S> {
void next(const T& t) {
pass(t);
}
void next(const T& t) { pass(t); }
void stop() { sink<T>::continuation().stop(); }
end<S>& operator>>=(end<T>& to) {
set_continuation(to);
return *this;
Expand All @@ -72,6 +74,7 @@ class iterator_end: public end<V> {
public:
iterator_end(const Iter& i): it(i) {}
void next(const V& value) { *it++ = value; }
void stop() {}
boost::shared_ptr< end<V> > clone() const { return boost::make_shared< iterator_end<V, Iter> >(it); }
};

Expand Down

0 comments on commit e752bc4

Please sign in to comment.