diff --git a/trunk/Makefile b/trunk/Makefile index eebb820..ac22e68 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -1,25 +1,24 @@ -SRC_DIR = src -PROJECT_NAME = pn -SRCS = $(wildcard $(SRC_DIR)/*.cpp) LIBS = boost_program_options boost_filesystem boost_system CFLAGS = -O2 -Wall -pedantic +PROJECT_NAME = pn +SRC_DIR = src +SRCS = $(wildcard $(SRC_DIR)/*.cpp) +OBJS = $(patsubst $(SRC_DIR)/%.cpp,%.o,$(SRCS)) + +builds = debug release +debug_flags = -ggdb +release_flags = -DNDEBUG -.PHONY: first debug release makedirs clean -first: debug -debug: - @make makedirs DIR=debug - @make debug/$(PROJECT_NAME) DIR=debug FLAGS=-ggdb -release: - @make makedirs DIR=release - @make release/$(PROJECT_NAME) DIR=release FLAGS=-DNDEBUG -makedirs: - -@mkdir -p $(dir $(subst $(SRC_DIR),$(DIR),$(SRCS))) $(dir $(subst $(SRC_DIR),.depend,$(SRCS))) +.PHONY: $(builds) clean +$(builds): %: %-makedirs %/$(PROJECT_NAME) +$(addsuffix -makedirs,$(builds)): %-makedirs: + -@mkdir -p $(dir $(subst $(SRC_DIR),$*,$(SRCS))) $(dir $(subst $(SRC_DIR),.depend,$(SRCS))) clean: - -@rm -rf debug release $(DIR) .depend + -@rm -rf $(builds) .depend --include $(patsubst $(SRC_DIR)/%.cpp, .depend/%.dep, $(SRCS)) +-include $(patsubst $(SRC_DIR)/%.cpp,.depend/%.dep,$(SRCS)) -$(DIR)/$(PROJECT_NAME): $(patsubst $(SRC_DIR)/%.cpp, $(DIR)/%.o, $(SRCS)) - g++ $^ -o $@ $(patsubst %,-l%,$(LIBS)) -$(DIR)/%.o: $(SRC_DIR)/%.cpp - g++ $< -c $(CFLAGS) -o $@ $(FLAGS) -MMD -MT $@ -MF .depend/$*.dep +$(addsuffix /%.o,$(builds)): $(SRC_DIR)/%.cpp + g++ $< -c -o $@ $(CFLAGS) $($(D@)_flags) -MMD -MT $@ -MF .depend/$*.dep +$(addsuffix /$(PROJECT_NAME),$(builds)): %$(PROJECT_NAME): $(addprefix %,$(OBJS)) + g++ $^ -o $@ $(addprefix -l,$(LIBS)) diff --git a/trunk/src/filesystem.h b/trunk/src/filesystem.h index 829b984..b6203fc 100644 --- a/trunk/src/filesystem.h +++ b/trunk/src/filesystem.h @@ -7,29 +7,26 @@ #include "logger.h" #include "functor_iterator.h" +#include "sequence.h" namespace fs { using namespace boost::filesystem; -template -class recursive { - Funct _funct; +class recursive: public seq { public: - typedef typename Funct::value_type value_type; - recursive(const Funct& funct): _funct(funct) {} - template - void operator()(const T& value) { + void operator()(const fs::path& p) { put(p); } + void operator()(const std::string& value) { if (!exists(value)) { logger::std_stream() << value << " does not exists" << std::endl; } else if (is_directory(value)) { remove_copy_if(recursive_directory_iterator(value), recursive_directory_iterator(), - functor_iterator(_funct), + functor_iterator(*this), std::not1(std::ptr_fun((bool(*)(const path&))(&is_regular_file)))); } else if (is_regular_file(value)) { - _funct(value); + put(value); } else { logger::std_stream() << value << " neither directory nor regular file" << std::endl; } diff --git a/trunk/src/functor_iterator.h b/trunk/src/functor_iterator.h index 0c95888..3c1bd7c 100644 --- a/trunk/src/functor_iterator.h +++ b/trunk/src/functor_iterator.h @@ -1,15 +1,12 @@ #ifndef _FUNCTOR_ITERATOR_H_ #define _FUNCTOR_ITERATOR_H_ -#include - -template +template class functor_iterator { - Funct _funct; + F _funct; public: - typedef typename Funct::value_type value_type; - functor_iterator(const Funct& funct): _funct(funct) {} - functor_iterator& operator=(const value_type& elem) { _funct(elem); return *this; } + functor_iterator(const F& funct): _funct(funct) {} + functor_iterator& operator=(const V& elem) { _funct(elem); return *this; } functor_iterator& operator*() { return *this; } functor_iterator& operator++() { return *this; } functor_iterator operator++(int) { return *this; } diff --git a/trunk/src/main.cpp b/trunk/src/main.cpp index 2440eb7..59ce905 100644 --- a/trunk/src/main.cpp +++ b/trunk/src/main.cpp @@ -3,6 +3,16 @@ #include "filesystem.h" #include "binary_functor.h" #include "comparer.h" +#include "sequence.h" + +class HasExtension { + const std::vector& _extensions; +public: + HasExtension(const std::vector& extensions): _extensions(extensions) { } + bool operator()(const fs::path& file) const { + return find(_extensions.begin(), _extensions.end(), file.extension()) != _extensions.end(); + } +}; int main(int argc, char* argv[]) { stderr_logger std_logger(argv[0]); @@ -10,8 +20,14 @@ int main(int argc, char* argv[]) { program_options po(argc, argv); - typedef std::ostream_iterator out_iter; - typedef binary_functor bin_funct; - for_each(po.input_files().begin(), po.input_files().end(), - fs::recursive(bin_funct(out_iter(std::cout), comparer()))); + make_pair(po.input_files().begin(), po.input_files().end()) + >>= fs::recursive() + >>= po.extensions().empty() + ? (seq&) The() + : The(HasExtension(po.extensions())) + // >>= clusterize() + // >>= comparator() + >>= The(std::ostream_iterator(std::cout, "\n")); + + return 0; } diff --git a/trunk/src/program_options.cpp b/trunk/src/program_options.cpp index 4b7d8bc..1e15392 100644 --- a/trunk/src/program_options.cpp +++ b/trunk/src/program_options.cpp @@ -9,14 +9,16 @@ namespace po = boost::program_options; program_options::program_options(int argc, char* argv[]) { const std::string usage = std::string("Usage: ") + argv[0] + " [OPTIONS] FILES\n"; try { + std::string extensions; po::options_description visible_options("Available options"); visible_options.add_options() + ("extensions", po::value(&extensions), "Search through files with ") ("help", "Print this message and exit") ; po::options_description command_line_options; command_line_options.add(visible_options).add_options() - ("files", po::value< std::vector >(&_input_files)) + ("files", po::value(&_input_files)) ; po::positional_options_description positional_options; @@ -35,6 +37,17 @@ program_options::program_options(int argc, char* argv[]) { std::cout << visible_options << "\n"; exit(0); } + + if (!extensions.empty()) { + for (size_t p = 0, p2 = 0; p2 != std::string::npos; p = p2 + 1) { + p2 = extensions.find(',', p); + std::string ext = extensions.substr(p, p2 != std::string::npos ? p2 - p : p2); + if (ext.length() > 0 && ext[0] != '.') { + ext = "." + ext; + } + _extensions.push_back(ext); + } + } } catch(std::exception const& e) { logger::std(e.what()); exit(1); diff --git a/trunk/src/program_options.h b/trunk/src/program_options.h index 9d37aaf..7686d65 100644 --- a/trunk/src/program_options.h +++ b/trunk/src/program_options.h @@ -8,9 +8,11 @@ class program_options { std::vector _input_files; + std::vector _extensions; public: program_options(int argc, char* argv[]); const std::vector& input_files() const { return _input_files; } + const std::vector& extensions() const { return _extensions; } }; #endif diff --git a/trunk/src/sequence.h b/trunk/src/sequence.h new file mode 100644 index 0000000..0b1861a --- /dev/null +++ b/trunk/src/sequence.h @@ -0,0 +1,77 @@ +#ifndef _SEQUENCE_H_ +#define _SEQUENCE_H_ + +template +struct end { + virtual void operator()(const S& v) = 0; +}; + +template +void operator>>=(const V& from, end& to) { + to(from); +} + +template +void operator>>=(const std::pair& from, end& to) { + for (Iter it = from.first; it != from.second; to(*it++)) ; +} + +template +void operator>>=(const std::pair& from, end& to) { + for (int i = 0; i < from.second; ++i) { + to(from.first()); + } +} + +template +class seq: public end { + end* e; +protected: + void put(const T& t) { + (*e)(t); + } +public: + end& operator>>=(end& to) { + e = &to; + return *this; + } +}; + +template +class iterator_end: public end { + Iter it; +public: + iterator_end(const Iter& i): it(i) {} + void operator()(const V& value) { *it++ = value; } +}; + +template +class filter: public seq { + P _p; +public: + filter(const P& p): _p(p) {} + void operator()(const T& value) { + if (_p(value)) { + put(value); + } + } +}; + +template +struct id: seq { + void operator()(const T& t) { put(t); } +}; + +template T& The() { static T r; return r; } +template T& The(const T& t) { static T r(t); return r; } +template class R, typename S> R& The() { static R r; return r; } +template class R, typename S> R& The(const S& s) { static R r(s); return r; } +template class R, typename S> R& The(const R& t) { static R r(t); return r; } +template class R, typename S, typename T> R& The() { static R r; return r; } +template class R, typename S, typename T> R& The(const T& t) { static R r(t); return r; } +template class R, typename S, typename T> R& The(const R& t) { static R r(t); return r; } +template class R, typename S, typename T, typename U> R& The() { static R r; return r; } +template class R, typename S, typename T, typename U> R& The(const U& u) { static R r(u); return r; } +template class R, typename S, typename T, typename U> R& The(const R& t) { static R r(t); return r; } + +#endif