diff --git a/example/cpp_comments_filter.hpp b/example/cpp_comments_filter.hpp new file mode 100755 index 0000000..5a01a47 --- /dev/null +++ b/example/cpp_comments_filter.hpp @@ -0,0 +1,128 @@ +// (C) Copyright Jonathan Turkanis 2005. +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Adapted from an example of James Kanze, with suggestions from Peter Dimov. +// See http://www.gabi-soft.fr/codebase-en.html. + +#ifndef BOOST_IOSTREAMS_CPP_COMMENTS_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_CPP_COMMENTS_FILTER_HPP_INCLUDED + +#include +#include // EOF. +#include // cin, cout. +#include +#include +#include + +namespace boost { namespace iostreams { namespace example { + +struct cpp_comments_base { + enum { + st_line_beginning, + st_normal, + st_open_slash, + st_close_slash, + st_open_star, + st_close_star, + st_quote, + st_escape_odd, + st_escape_even + }; + cpp_comments_base() : state_(st_normal) { } + int state_; +}; + +class cpp_comments_stdio_filter : public stdio_filter { +public: + explicit cpp_comments_stdio_filter() { } +private: + void do_filter() + { + int c; + while ((c = std::cin.get()) != EOF) { + switch (state_) { + case st_normal: + if (c == '/') { + state_ = st_open_slash; + } else if (c == '"' || c == '<') { + + } + break; + case st_open_slash: + case st_close_slash: + case st_open_star: + case st_close_star: + case st_quote: + case st_escape_odd: + case st_escape_even: + } + } + } + void do_close() { state_ = st_normal; } +}; + +//class cpp_comments_input_filter : public input_filter { +//public: +// explicit cpp_comments_input_filter(char comment_char = '#') +// : comment_char_(comment_char), skip_(false) +// { } +// +// template +// int get(Source& src) +// { +// int c; +// while (true) { +// if ((c = boost::iostreams::get(src)) == EOF || c == WOULD_BLOCK) +// break; +// skip_ = c == comment_char_ ? +// true : +// c == '\n' ? +// false : +// skip_; +// if (!skip_) +// break; +// } +// return c; +// } +// +// template +// void close(Source&) { skip_ = false; } +//private: +// char comment_char_; +// bool skip_; +//}; +// +//class cpp_comments_output_filter : public output_filter { +//public: +// explicit cpp_comments_output_filter(char comment_char = '#') +// : comment_char_(comment_char), skip_(false) +// { } +// +// template +// bool put(Sink& dest, int c) +// { +// skip_ = c == comment_char_ ? +// true : +// c == '\n' ? +// false : +// skip_; +// +// if (skip_) +// return true; +// +// return iostreams::put(dest, c); +// } +// +// template +// void close(Source&) { skip_ = false; } +//private: +// char comment_char_; +// bool skip_; +//}; + +} } } // End namespaces example, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_CPP_COMMENTS_FILTER_HPP_INCLUDED diff --git a/example/dictionary_filter.hpp b/example/dictionary_filter.hpp new file mode 100755 index 0000000..094c0cc --- /dev/null +++ b/example/dictionary_filter.hpp @@ -0,0 +1,209 @@ +// (C) Copyright Jonathan Turkanis 2003. +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DICTIONARY_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_DICTIONARY_FILTER_HPP_INCLUDED + +#include +#include // EOF. +#include // cin, cout. +#include +#include +#include +#include +#include + +namespace boost { namespace iostreams { namespace example { + +class dictionary { +public: + dictionary(const std::locale& loc = std::locale::classic()); + void add(std::string key, const std::string& value); + bool replace(std::string& key); + const std::locale& getloc() const; + std::string::size_type max_length() const { return max_length_; } +private: + typedef std::map map_type; + void tolower(std::string& str); + map_type map_; + std::locale loc_; + std::string::size_type max_length_; +}; + +class dictionary_stdio_filter : public stdio_filter { +public: + dictionary_stdio_filter(dictionary& d) : dictionary_(d) { } +private: + void do_filter() + { + using namespace std; + while (true) { + int c = std::cin.get(); + if (c == EOF || !std::isalpha(c, dictionary_.getloc())) { + dictionary_.replace(current_word_); + cout.write( current_word_.data(), + static_cast(current_word_.size()) ); + current_word_.clear(); + if (c == EOF) + break; + cout.put(c); + } else { + current_word_ += c; + } + } + } + dictionary& dictionary_; + std::string current_word_; +}; + +class dictionary_input_filter : public input_filter { +public: + dictionary_input_filter(dictionary& d) + : dictionary_(d), off_(std::string::npos), eof_(false) + { } + + template + int get(Source& src) + { + // Handle unfinished business. + if (eof_) + return EOF; + if (off_ != std::string::npos && off_ < current_word_.size()) + return current_word_[off_++]; + if (off_ == current_word_.size()) { + current_word_.clear(); + off_ = std::string::npos; + } + + // Compute curent word. + while (true) { + int c; + if ((c = iostreams::get(src)) == WOULD_BLOCK) + return WOULD_BLOCK; + + if (c == EOF || !std::isalpha(c, dictionary_.getloc())) { + dictionary_.replace(current_word_); + off_ = 0; + if (c == EOF) + eof_ = true; + else + current_word_ += c; + break; + } else { + current_word_ += c; + } + } + + return this->get(src); // Note: current_word_ is not empty. + } + + template + void close(Source&) + { + current_word_.clear(); + off_ = std::string::npos; + eof_ = false; + } +private: + dictionary& dictionary_; + std::string current_word_; + std::string::size_type off_; + bool eof_; +}; + +class dictionary_output_filter : public output_filter { +public: + typedef std::map map_type; + dictionary_output_filter(dictionary& d) + : dictionary_(d), off_(std::string::npos) + { } + + template + bool put(Sink& dest, int c) + { + if (off_ != std::string::npos && !write_current_word(dest)) + return false; + + if (!std::isalpha(c, dictionary_.getloc())) { + dictionary_.replace(current_word_); + off_ = 0; + } + + current_word_ += c; + return true; + } + + template + void close(Sink& dest) + { + if (off_ == std::string::npos) + dictionary_.replace(current_word_); + if (!current_word_.empty()) + write_current_word(dest); + current_word_.clear(); + off_ = std::string::npos; + } +private: + template + bool write_current_word(Sink& dest) + { + using namespace std; + streamsize amt = static_cast(current_word_.size() - off_); + streamsize result = + iostreams::write(dest, current_word_.data() + off_, amt); + if (result == amt) { + current_word_.clear(); + off_ = string::npos; + return true; + } else { + off_ += result; + return false; + } + } + + dictionary& dictionary_; + std::string current_word_; + std::string::size_type off_; + bool initialized_; +}; + +//------------------Implementation of dictionary------------------------------// + +inline dictionary::dictionary(const std::locale& loc) : loc_(loc) { } + +inline void dictionary::add(std::string key, const std::string& value) +{ + max_length_ = max_length_ < key.size() ? key.size() : max_length_; + tolower(key); + map_[key] = value; +} + +inline bool dictionary::replace(std::string& key) +{ + using namespace std; + string copy(key); + tolower(copy); + map_type::iterator it = map_.find(key); + if (it == map_.end()) + return false; + string& value = it->second; + if (!value.empty() && !key.empty() && std::isupper(key[0], loc_)) + value[0] = std::toupper(value[0], loc_); + key = value; + return true; +} + +inline const std::locale& dictionary::getloc() const { return loc_; } + +inline void dictionary::tolower(std::string& str) +{ + for (std::string::size_type z = 0, len = str.size(); z < len; ++z) + str[z] = std::tolower(str[z], loc_); +} + +} } } // End namespaces example, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DICTIONARY_FILTER_HPP_INCLUDED diff --git a/example/finite_state_filter.hpp b/example/finite_state_filter.hpp new file mode 100755 index 0000000..963f3ff --- /dev/null +++ b/example/finite_state_filter.hpp @@ -0,0 +1,254 @@ +// (C) Copyright Jonathan Turkanis 2005. +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Adapted from an example of James Kanze, with suggestions from Peter Dimov. +// See http://www.gabi-soft.fr/codebase-en.html. + +#ifndef BOOST_IOSTREAMS_FINITE_STATE_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_FINITE_STATE_FILTER_HPP_INCLUDED + +#include +#include // EOF. +#include // cin, cout. +#include +#include +#include // JOIN. +#include // Localizable. +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace iostreams { namespace example { + +//------------------Definition of basic character classes---------------------// + +#define BOOST_IOSTREAMS_CHARACTER_CLASS(class) \ + struct BOOST_JOIN(is_, class) { \ + template \ + static bool test(Ch event, const std::locale& loc) \ + { return std::BOOST_JOIN(is, class)(event, loc); } \ + }; \ + /**/ + +BOOST_IOSTREAMS_CHARACTER_CLASS(alnum) +BOOST_IOSTREAMS_CHARACTER_CLASS(alpha) +BOOST_IOSTREAMS_CHARACTER_CLASS(cntrl) +BOOST_IOSTREAMS_CHARACTER_CLASS(digit) +BOOST_IOSTREAMS_CHARACTER_CLASS(graph) +BOOST_IOSTREAMS_CHARACTER_CLASS(lower) +BOOST_IOSTREAMS_CHARACTER_CLASS(print) +BOOST_IOSTREAMS_CHARACTER_CLASS(punct) +BOOST_IOSTREAMS_CHARACTER_CLASS(space) +BOOST_IOSTREAMS_CHARACTER_CLASS(upper) +BOOST_IOSTREAMS_CHARACTER_CLASS(xdigit) + +#undef BOOST_IOSTREAMS_CHARACTER_CLASS + +template +struct is { + template + static bool test(Ch event, const std::locale& loc) + { + return event == C; + } +}; + +struct is_any { + template + static bool test(Ch event, const std::locale& loc) { return true; } +}; + +//------------------Definition of base class for finite state filters---------// + +template +class finite_state_filter_base { +public: + typedef Ch char_type; + //typedef typename Derived::char_type char_type; + void imbue(const std::locale& loc) { loc_ = loc; } + const std::locale& getloc() const { return loc_; } +protected: + + // Template whose instantiations make up transition table. + + template< int State, + typename CharacterClass, + int NextState, + void (Derived::*Action)(char_type) > + struct rule { + typedef CharacterClass character_class; + static const int state = State; + static const int next_state = NextState; + static void execute(Derived& d, char event) + { + (d.*action)(event); + } + }; + + // Default event handlers. + + void on_eof() { } + void on_any() { } + + // Stack interface. + + bool empty() const { return buf_.empty(); } + void push(char_type c) { buf_ += c; } + char_type pop() + { + char_type result = buf_[off_++]; + if (off_ == buf_.size()) + clear(); + return result; + } + void clear() + { + buf_.clear(); + off_ = 0; + } +private: + typedef std::basic_string string_type; + typedef typename string_type::size_type size_type; + std::locale loc_; + string_type buf_; + size_type off_; +}; + +//------------------Definition of finite_state_filter_impl--------------------// + +template +class finite_state_filter_impl : protected FiniteStateFilter +{ +private: + //typedef finite_state_filter_base base_type; + //BOOST_STATIC_ASSERT((is_base_and_derived::value)); + + template + struct process_event_impl; +public: + typedef typename io_char::type char_type; + + finite_state_filter_impl() : state_(FiniteStateFilter::initial_state) { } + + template + finite_state_filter_impl(const T0& t0) + : FiniteStateFilter(t0), state_(FiniteStateFilter::initial_state) + { } + + template + finite_state_filter_impl(const T0& t0, const T1& t1) + : FiniteStateFilter(t0, t1), state_(FiniteStateFilter::initial_state) + { } + + template + finite_state_filter_impl(const T0& t0, const T1& t1, const T1& t2) + : FiniteStateFilter(t0, t1, t2), state_(FiniteStateFilter::initial_state) + { } +protected: + int process_event(char_type c) + { + typedef typename FiniteStateFilter::transition_table transitions; + typedef typename mpl::begin:type first; + //typedef typename mpl::end:type last; + //return process_event_impl::execute(*this, state_, c); + return 0; + } + + int& state() { return state_; } +private: + template + struct process_event_impl { + static int execute(FiniteStateFilter& filter, int state, char_type event) + { + typedef typename mpl::deref::type rule; + typedef typename mpl::next::type next; + typedef typename rule_type::character_class character_class; + + if ( state == rule_type::state && + character_class::test(event, filter.getloc()) ) + { + // Rule applies. + rule_type::execute(filter, event); + return rule_type::next_state; + } + + // Rule is inapplicable: try next rule. + return process_event_impl::execute(filter, state, event); + } + }; + + template + struct process_event_impl { + static int execute(FiniteStateFilter& filter, int state, char_type) + { + filter.on_any(); // Default action. + return state; + } + }; + + int state_; +}; + +//------------------Definition of base finite_state_stdio_filter--------------// + +template +class finite_state_stdio_filter + : public basic_stdio_filter, + public finite_state_filter_impl +{ +private: + typedef finite_state_filter_impl base_type; +public: + typedef typename base_type::char_type char_type; + struct io_category : stdio_filter::io_category, localizable_tag { }; + + finite_state_stdio_filter() { } + + template + finite_state_stdio_filter(const T0& t0) + : base_type(t0) + { } + + template + finite_state_stdio_filter(const T0& t0, const T1& t1) + : base_type(t0, t1) + { } + + template + finite_state_stdio_filter(const T0& t0, const T1& t1, const T1& t2) + : base_type(t0, t1, t2) + { } +private: + void do_filter() + { + using namespace std; + while (true) { + flush(); + + int c; + if ((c = cin.get()) != EOF) + process_event((char) c); + else { + this->on_eof(); + flush(); + break; + } + } + } + void do_close() { + this->clear(); + this->state() = FiniteStateFilter::initial_state; + } + void flush() { while (!this->empty()) std::cout.put(this->pop()); } +}; + +} } } // End namespaces example, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_FINITE_STATE_FILTER_HPP_INCLUDED diff --git a/example/line_wrapping_filter.hpp b/example/line_wrapping_filter.hpp new file mode 100755 index 0000000..6054ca8 --- /dev/null +++ b/example/line_wrapping_filter.hpp @@ -0,0 +1,130 @@ +// (C) Copyright Jonathan Turkanis 2005. +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) + +// Adapted from an example of James Kanze. See +// http://www.gabi-soft.fr/codebase-en.html. + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_LINE_WRAPPING_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_LINE_WRAPPING_FILTER_HPP_INCLUDED + +#include // EOF. +#include // output_filter. +#include +#include // boost::iostreams::put. + +namespace boost { namespace iostreams { namespace example { + +class line_wrapping_stdio_filter : public stdio_filter { +public: + explicit line_wrapping_stdio_filter(int line_length = 80) + : line_length_(line_length), col_no_(0) + { } +private: + void do_filter() + { + int c; + while ((c = std::cin.get()) != EOF) { + if (c != '\n' && col_no_ >= line_length_) + put_char('\n'); + put_char(c); + } + } + void do_close() { col_no_ = 0; } + void put_char(int c) + { + std::cout.put(c); + if (c != '\n') + ++col_no_; + else + col_no_ = 0; + } + int line_length_; + int col_no_; +}; + +class line_wrapping_input_filter : public input_filter { +public: + explicit line_wrapping_input_filter(int line_length = 80) + : line_length_(line_length), col_no_(0), has_next_(false) + { } + + template + int get(Source& src) + { + if (has_next_) { + has_next_ = false; + return get_char(next_); + } + + int c; + if ((c = iostreams::get(src)) == EOF || c == WOULD_BLOCK) + return c; + + if (c != '\n' && col_no_ >= line_length_) { + next_ = c; + has_next_ = true; + return get_char('\n'); + } + + return get_char(c); + } + + template + void close(Sink&) + { + col_no_ = 0; + has_next_; + } +private: + int get_char(int c) + { + if (c != '\n') + ++col_no_; + else + col_no_ = 0; + return c; + } + int line_length_; + int col_no_; + int next_; + int has_next_; +}; + +class line_wrapping_output_filter : public output_filter { +public: + explicit line_wrapping_output_filter(int line_length = 80) + : line_length_(line_length), col_no_(0) + { } + + template + bool put(Sink& dest, int c) + { + if (c != '\n' && col_no_ >= line_length_ && !put_char(dest, '\n')) + return false; + return put_char(dest, c); + } + + template + void close(Sink&) { col_no_ = 0; } +private: + template + bool put_char(Sink& dest, int c) + { + if (!iostreams::put(dest, c)) + return false; + if (c != '\n') + ++col_no_; + else + col_no_ = 0; + return true; + } + int line_length_; + int col_no_; +}; + +} } } // End namespaces example, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_LINE_WRAPPING_FILTER_HPP_INCLUDED diff --git a/example/shell_comments_filter.hpp b/example/shell_comments_filter.hpp new file mode 100755 index 0000000..fe65f45 --- /dev/null +++ b/example/shell_comments_filter.hpp @@ -0,0 +1,106 @@ +// (C) Copyright Jonathan Turkanis 2005. +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Adapted from an example of James Kanze, with suggestions from Peter Dimov. +// See http://www.gabi-soft.fr/codebase-en.html. + +#ifndef BOOST_IOSTREAMS_SHELL_COMMENTS_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_SHELL_COMMENTS_FILTER_HPP_INCLUDED + +#include +#include // EOF. +#include // cin, cout. +#include +#include +#include + +namespace boost { namespace iostreams { namespace example { + +class shell_comments_stdio_filter : public stdio_filter { +public: + explicit shell_comments_stdio_filter(char comment_char = '#') + : comment_char_(comment_char) + { } +private: + void do_filter() + { + bool skip = false; + int c; + while ((c = std::cin.get()) != EOF) { + skip = c == comment_char_ ? + true : + c == '\n' ? + false : + skip; + if (!skip) + std::cout.put(c); + } + } + char comment_char_; +}; + +class shell_comments_input_filter : public input_filter { +public: + explicit shell_comments_input_filter(char comment_char = '#') + : comment_char_(comment_char), skip_(false) + { } + + template + int get(Source& src) + { + int c; + while (true) { + if ((c = boost::iostreams::get(src)) == EOF || c == WOULD_BLOCK) + break; + skip_ = c == comment_char_ ? + true : + c == '\n' ? + false : + skip_; + if (!skip_) + break; + } + return c; + } + + template + void close(Source&) { skip_ = false; } +private: + char comment_char_; + bool skip_; +}; + +class shell_comments_output_filter : public output_filter { +public: + explicit shell_comments_output_filter(char comment_char = '#') + : comment_char_(comment_char), skip_(false) + { } + + template + bool put(Sink& dest, int c) + { + skip_ = c == comment_char_ ? + true : + c == '\n' ? + false : + skip_; + + if (skip_) + return true; + + return iostreams::put(dest, c); + } + + template + void close(Source&) { skip_ = false; } +private: + char comment_char_; + bool skip_; +}; + +} } } // End namespaces example, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_SHELL_COMMENTS_FILTER_HPP_INCLUDED diff --git a/example/tab_expanding_filter.hpp b/example/tab_expanding_filter.hpp new file mode 100755 index 0000000..1df9bc1 --- /dev/null +++ b/example/tab_expanding_filter.hpp @@ -0,0 +1,156 @@ +// (C) Copyright Jonathan Turkanis 2005. +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Adapted from an example of James Kanze, with suggestions from Rob Stewart. +// See http://www.gabi-soft.fr/codebase-en.html. + +#ifndef BOOST_IOSTREAMS_TAB_EXPANDING_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_TAB_EXPANDING_FILTER_HPP_INCLUDED + +#include +#include // EOF. +#include // cin, cout. +#include +#include +#include + +namespace boost { namespace iostreams { namespace example { + +class tab_expanding_stdio_filter : public stdio_filter { +public: + explicit tab_expanding_stdio_filter(int tab_size = 8) + : tab_size_(tab_size), col_no_(0) + { + assert(tab_size > 0); + } +private: + void do_filter() + { + int c; + while ((c = std::cin.get()) != EOF) { + if (c == '\t') { + int spaces = tab_size_ - (col_no_ % tab_size_); + for (; spaces > 0; --spaces) + put_char(' '); + } else { + put_char(c); + } + } + } + void do_close() { col_no_ = 0; } + void put_char(int c) + { + std::cout.put(c); + if (c == '\n') { + col_no_ = 0; + } else { + ++col_no_; + } + } + int tab_size_; + int col_no_; +}; + +class tab_expanding_input_filter : public input_filter { +public: + explicit tab_expanding_input_filter(int tab_size = 8) + : tab_size_(tab_size), col_no_(0), spaces_(0) + { + assert(tab_size > 0); + } + + template + int get(Source& src) + { + if (spaces_ > 0) { + --spaces_; + return get_char(' '); + } + + int c; + if ((c = iostreams::get(src)) == EOF || c == WOULD_BLOCK) + return c; + + if (c != '\t') + return get_char(c); + + // Found a tab. Call this filter recursively. + spaces_ = tab_size_ - (col_no_ % tab_size_); + return this->get(src); + } + + template + void close(Source&) + { + col_no_ = 0; + spaces_ = 0; + } +private: + int get_char(int c) + { + if (c == '\n') { + col_no_ = 0; + } else { + ++col_no_; + } + return c; + } + int tab_size_; + int col_no_; + int spaces_; +}; + +class tab_expanding_output_filter : public output_filter { +public: + explicit tab_expanding_output_filter(int tab_size = 8) + : tab_size_(tab_size), col_no_(0), spaces_(0) + { + assert(tab_size > 0); + } + + template + bool put(Sink& dest, int c) + { + for (; spaces_ > 0; --spaces_) + if (!put_char(dest, ' ')) + return false; + + if (c == '\t') { + spaces_ = tab_size_ - (col_no_ % tab_size_) - 1; + return this->put(dest, ' '); + } + + return put_char(dest, c); + } + + template + void close(Sink&) + { + col_no_ = 0; + spaces_ = 0; + } +private: + template + bool put_char(Sink& dest, int c) + { + if (boost::iostreams::put(dest, c)) { + if (c == '\n') { + col_no_ = 0; + } else { + ++col_no_; + } + return true; + } + return false; + } + int tab_size_; + int col_no_; + int spaces_; +}; + +} } } // End namespaces example, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_TAB_EXPANDING_FILTER_HPP_INCLUDED diff --git a/example/test.cpp b/example/test.cpp new file mode 100755 index 0000000..509a62f --- /dev/null +++ b/example/test.cpp @@ -0,0 +1,498 @@ +// (C) Copyright Jonathan Turkanis 2005. +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include // failure. +#include +#include +#include +#include +#include +#include "./dictionary_filter.hpp" +//#include "./finite_state_filter.hpp" +#include "./line_wrapping_filter.hpp" +#include "./shell_comments_filter.hpp" +#include "./tab_expanding_filter.hpp" +#include "./unix2dos_filter.hpp" + +using boost::unit_test::test_suite; +namespace io = boost::iostreams; +namespace ex = boost::iostreams::example; + +#include +#include +#include +#include +#include + +//------------------dictionary_filter test------------------------------------// + +void dictionary_filter_test() +{ + using namespace std; + + io::example::dictionary d; + + // See http://english2american.com. + d.add("answerphone", "answering machine"); + d.add("bloke", "guy"); + d.add("gearbox", "transmission"); + d.add("ironmonger", "hardware shop"); + d.add("loo", "restroom"); + d.add("lorry", "truck"); + //d.add("off-license", "liquor store"); + d.add("rubber", "eraser"); + d.add("spanner", "monkey wrench"); + d.add("telly", "TV"); + d.add("tyre", "tire"); + d.add("waistcoat", "vest"); + d.add("windscreen", "windshield"); + + const char* input = + "I had a message on my answerphone from the bloke at the car " + "dealership that the windscreen and tyre on my lorry were replaced. " + "However, the gearbox would not be ready until tomorrow since the " + "spanner that they needed was broken and they had to go to the " + "ironmonger to buy a replacement. Since my lorry was not ready, " + "I decided to take the bus downtown and buy a new waistcoat. I " + "also stopped at the liquor store to buy some wine. I came home " + "and watched the telly and drank my wine. I also worked on a " + "crossword puzzle. Fortunately I had a pencil with a new rubber. " + "During that evening I made frequent trips to the loo due to my " + "excessive drinking."; + + const char* output = + "I had a message on my answering machine from the guy at the car " + "dealership that the windshield and tire on my truck were replaced. " + "However, the transmission would not be ready until tomorrow since " + "the monkey wrench that they needed was broken and they had to go to " + "the hardware shop to buy a replacement. Since my truck was not ready, " + "I decided to take the bus downtown and buy a new vest. I also stopped " + "at the liquor store to buy some wine. I came home and watched the TV " + "and drank my wine. I also worked on a crossword puzzle. Fortunately I " + "had a pencil with a new eraser. During that evening I made frequent " + "trips to the restroom due to my excessive drinking."; + + BOOST_CHECK( + io::test_input_filter( io::example::dictionary_stdio_filter(d), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::dictionary_stdio_filter(d), + input, output ) + ); + + BOOST_CHECK( + io::test_input_filter( io::example::dictionary_input_filter(d), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::dictionary_output_filter(d), + input, output ) + ); +} + +//------------------finite_state_filter test----------------------------------// + +//struct dos2unix_filter +// : ex::finite_state_filter_base +//{ +// typedef dos2unix_filter self; +// typedef char char_type; +// +// static const int initial_state = 0; +// static const int found_cr = 1; +// +// void on_cr(char) { } +// void on_any(char c) { push(c); } +// void on_error(char) +// { +// throw std::ios_base::failure("bad input"); +// } +// +// typedef boost::mpl::vector< +// rule, found_cr, &self::on_cr>, +// rule, initial_state, &self::on_error>, +// rule, initial_state, &self::on_any>, +// rule +// > transition_table; +//}; +// +//void finite_state_filter_test() +//{ +// using namespace std; +// +// const char* input = +// "When I was one-and-twenty\n" +// "I heard a wise man say,\n" +// "'Give crowns and pounds and guineas\n" +// "But not your heart away;\n" +// "\n" +// "Give pearls away and rubies\n" +// "But keep your fancy free.'\n" +// "But I was one-and-twenty,\n" +// "No use to talk to me.\n" +// "\n" +// "When I was one-and-twenty\n" +// "I heard him say again,\n" +// "'The heart out of the bosom\n" +// "Was never given in vain;\n" +// "'Tis paid with sighs a plenty\n" +// "And sold for endless rue.'\n" +// "And I am two-and-twenty,\n" +// "And oh, 'tis true, 'tis true."; +// +// const char* output = +// "When I was one-and-twenty\r\n" +// "I heard a wise man say,\r\n" +// "'Give crowns and pounds and guineas\r\n" +// "But not your heart away;\r\n" +// "\r\n" +// "Give pearls away and rubies\r\n" +// "But keep your fancy free.'\r\n" +// "But I was one-and-twenty,\r\n" +// "No use to talk to me.\r\n" +// "\r\n" +// "When I was one-and-twenty\r\n" +// "I heard him say again,\r\n" +// "'The heart out of the bosom\r\n" +// "Was never given in vain;\r\n" +// "'Tis paid with sighs a plenty\r\n" +// "And sold for endless rue.'\r\n" +// "And I am two-and-twenty,\r\n" +// "And oh, 'tis true, 'tis true."; +// +// typedef ex::finite_state_stdio_filter dos2unix_stdio_filter; +// +// BOOST_CHECK( +// io::test_input_filter(dos2unix_stdio_filter(), input, output) +// ); +// +// //BOOST_CHECK( +// // io::test_output_filter( io::example::finite_state_stdio_filter(), +// // input, output ) +// //); +// +// //BOOST_CHECK( +// // io::test_input_filter( io::example::finite_state_input_filter(), +// // input, output ) +// //); +// +// //BOOST_CHECK( +// // io::test_output_filter( io::example::finite_state_output_filter(), +// // input, output ) +// //); +//} + +//------------------line_wrapping_filter test---------------------------------// + +void line_wrapping_filter_test() +{ + using namespace std; + + const char* input = + "I had a message on my answerphone from the bloke at the car \n" + "dealership that the windscreen and tyre on my lorry were replaced. \n" + "However, the gearbox would not be ready until tomorrow since the \n" + "spanner that they needed was broken and they had to go to the \n" + "ironmonger to buy a replacement. Since my lorry was not ready, \n" + "I decided to take the bus downtown and buy a new waistcoat. I \n" + "also stopped at the liquor store to buy some wine. I came home \n" + "and watched the telly and drank my wine. I also worked on a \n" + "crossword puzzle. Fortunately I had a pencil with a new rubber. \n" + "During that evening I made frequent trips to the loo due to my \n" + "excessive drinking."; + + const char* output = + "I had a message on my answerphone from t\n" + "he bloke at the car \n" + "dealership that the windscreen and tyre \n" + "on my lorry were replaced. \n" + "However, the gearbox would not be ready \n" + "until tomorrow since the \n" + "spanner that they needed was broken and \n" + "they had to go to the \n" + "ironmonger to buy a replacement. Since m\n" + "y lorry was not ready, \n" + "I decided to take the bus downtown and b\n" + "uy a new waistcoat. I \n" + "also stopped at the liquor store to buy \n" + "some wine. I came home \n" + "and watched the telly and drank my wine.\n" + " I also worked on a \n" + "crossword puzzle. Fortunately I had a pe\n" + "ncil with a new rubber. \n" + "During that evening I made frequent trip\n" + "s to the loo due to my \n" + "excessive drinking."; + + BOOST_CHECK( + io::test_input_filter( io::example::line_wrapping_stdio_filter(40), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::line_wrapping_stdio_filter(40), + input, output ) + ); + + BOOST_CHECK( + io::test_input_filter( io::example::line_wrapping_input_filter(40), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::line_wrapping_output_filter(40), + input, output ) + ); +} + +//------------------shell_comments_filter test--------------------------------// + +void shell_comments_filter_test() +{ + using namespace std; + + const char* input = // From . + "lib boost_filesystem\n" + " : ../src/$(SOURCES).cpp\n" + " : # build requirements\n" + " [ common-names ] # magic for install and auto-link features\n" + " $(BOOST_ROOT) $(BOOST_ROOT)\n" + " exception.cpp operations_posix_windows.cpp\n" + " : debug release # build variants\n" + " ;\n" + "\n" + "dll boost_filesystem\n" + " : ../src/$(SOURCES).cpp\n" + " : # build requirements\n" + " [ common-names ] # magic for install and auto-link features\n" + " BOOST_FILESYSTEM_DYN_LINK=1 # tell source we're building dll's\n" + " dynamic # build only for dynamic runtimes\n" + " $(BOOST_ROOT) $(BOOST_ROOT)\n" + " exception.cpp operations_posix_windows.cpp\n" + " : debug release # build variants\n" + " ;"; + + const char* output = + "lib boost_filesystem\n" + " : ../src/$(SOURCES).cpp\n" + " : \n" + " [ common-names ] \n" + " $(BOOST_ROOT) $(BOOST_ROOT)\n" + " exception.cpp operations_posix_windows.cpp\n" + " : debug release \n" + " ;\n" + "\n" + "dll boost_filesystem\n" + " : ../src/$(SOURCES).cpp\n" + " : \n" + " [ common-names ] \n" + " BOOST_FILESYSTEM_DYN_LINK=1 \n" + " dynamic \n" + " $(BOOST_ROOT) $(BOOST_ROOT)\n" + " exception.cpp operations_posix_windows.cpp\n" + " : debug release \n" + " ;"; + + BOOST_CHECK( + io::test_input_filter( io::example::shell_comments_stdio_filter(), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::shell_comments_stdio_filter(), + input, output ) + ); + + BOOST_CHECK( + io::test_input_filter( io::example::shell_comments_input_filter(), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::shell_comments_output_filter(), + input, output ) + ); +} + +//------------------tab_expanding_filter test---------------------------------// + +void tab_expanding_filter_test() +{ + using namespace std; + + const char* input = + "class tab_expanding_stdio_filter : public stdio_filter {\n" + "public:\n" + "\texplicit tab_expanding_stdio_filter(int\ttab_size = 8)\n" + "\t\t: tab_size_(tab_size), col_no_(0)\n" + "\t{\n" + "\t\tassert(tab_size\t> 0);\n" + "\t}\n" + "private:\n" + "\tvoid do_filter()\n" + "\t{\n" + "\t\tint\tc;\n" + "\t\twhile ((c = std::cin.get()) != EOF) {\n" + "\t\t\tif (c == '\\t') {\n" + "\t\t\t\tint\tspaces = tab_size_ - (col_no_ %\ttab_size_);\n" + "\t\t\t\tfor\t(; spaces >\t0; --spaces)\n" + "\t\t\t\t\tput_char(' ');\n" + "\t\t\t} else {\n" + "\t\t\t\tput_char(c);\n" + "\t\t\t}\n" + "\t\t}\n" + "\t}\n" + "\tvoid do_close()\t{ col_no_ =\t0; }\n" + "\tvoid put_char(int c)\n" + "\t{\n" + "\t\tstd::cout.put(c);\n" + "\t\tif (c == '\\n') {\n" + "\t\t\tcol_no_\t= 0;\n" + "\t\t} else {\n" + "\t\t\t++col_no_;\n" + "\t\t}\n" + "\t}\n" + "\tint\t tab_size_;\n" + "\tint\t col_no_;\n" + "};"; + + const char* output = + "class tab_expanding_stdio_filter : public stdio_filter {\n" + "public:\n" + " explicit tab_expanding_stdio_filter(int tab_size = 8)\n" + " : tab_size_(tab_size), col_no_(0)\n" + " {\n" + " assert(tab_size > 0);\n" + " }\n" + "private:\n" + " void do_filter()\n" + " {\n" + " int c;\n" + " while ((c = std::cin.get()) != EOF) {\n" + " if (c == '\\t') {\n" + " int spaces = tab_size_ - (col_no_ % tab_size_);\n" + " for (; spaces > 0; --spaces)\n" + " put_char(' ');\n" + " } else {\n" + " put_char(c);\n" + " }\n" + " }\n" + " }\n" + " void do_close() { col_no_ = 0; }\n" + " void put_char(int c)\n" + " {\n" + " std::cout.put(c);\n" + " if (c == '\\n') {\n" + " col_no_ = 0;\n" + " } else {\n" + " ++col_no_;\n" + " }\n" + " }\n" + " int tab_size_;\n" + " int col_no_;\n" + "};"; + + BOOST_CHECK( + io::test_input_filter( io::example::tab_expanding_stdio_filter(4), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::tab_expanding_stdio_filter(4), + input, output ) + ); + + BOOST_CHECK( + io::test_input_filter( io::example::tab_expanding_input_filter(4), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::tab_expanding_output_filter(4), + input, output ) + ); +} + +//------------------unix2dos_filter test--------------------------------------// + +void unix2dos_filter_test() +{ + using namespace std; + + const char* input = + "When I was one-and-twenty\n" + "I heard a wise man say,\n" + "'Give crowns and pounds and guineas\n" + "But not your heart away;\n" + "\n" + "Give pearls away and rubies\n" + "But keep your fancy free.'\n" + "But I was one-and-twenty,\n" + "No use to talk to me.\n" + "\n" + "When I was one-and-twenty\n" + "I heard him say again,\n" + "'The heart out of the bosom\n" + "Was never given in vain;\n" + "'Tis paid with sighs a plenty\n" + "And sold for endless rue.'\n" + "And I am two-and-twenty,\n" + "And oh, 'tis true, 'tis true."; + + const char* output = + "When I was one-and-twenty\r\n" + "I heard a wise man say,\r\n" + "'Give crowns and pounds and guineas\r\n" + "But not your heart away;\r\n" + "\r\n" + "Give pearls away and rubies\r\n" + "But keep your fancy free.'\r\n" + "But I was one-and-twenty,\r\n" + "No use to talk to me.\r\n" + "\r\n" + "When I was one-and-twenty\r\n" + "I heard him say again,\r\n" + "'The heart out of the bosom\r\n" + "Was never given in vain;\r\n" + "'Tis paid with sighs a plenty\r\n" + "And sold for endless rue.'\r\n" + "And I am two-and-twenty,\r\n" + "And oh, 'tis true, 'tis true."; + + BOOST_CHECK( + io::test_input_filter( io::example::unix2dos_stdio_filter(), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::unix2dos_stdio_filter(), + input, output ) + ); + + BOOST_CHECK( + io::test_input_filter( io::example::unix2dos_input_filter(), + input, output ) + ); + + BOOST_CHECK( + io::test_output_filter( io::example::unix2dos_output_filter(), + input, output ) + ); +} + +test_suite* init_unit_test_suite(int, char* []) +{ + test_suite* test BOOST_TEST_SUITE("example test"); + test->add(BOOST_TEST_CASE(&dictionary_filter_test)); + test->add(BOOST_TEST_CASE(&tab_expanding_filter_test)); + test->add(BOOST_TEST_CASE(&line_wrapping_filter_test)); + test->add(BOOST_TEST_CASE(&shell_comments_filter_test)); + test->add(BOOST_TEST_CASE(&unix2dos_filter_test)); + return test; +} diff --git a/example/unix2dos_filter.hpp b/example/unix2dos_filter.hpp new file mode 100755 index 0000000..d3d9648 --- /dev/null +++ b/example/unix2dos_filter.hpp @@ -0,0 +1,98 @@ +// (C) Copyright Jonathan Turkanis 2005. +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_UNIX2DOS_FILTER_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_UNIX2DOS_FILTER_FILTER_HPP_INCLUDED + +#include +#include // EOF. +#include // cin, cout. +#include +#include +#include + +namespace boost { namespace iostreams { namespace example { + +class unix2dos_stdio_filter : public stdio_filter { +private: + void do_filter() + { + int c; + while ((c = std::cin.get()) != EOF) { + if (c == '\n') + std::cout.put('\r'); + std::cout.put(c); + } + } +}; + +class unix2dos_input_filter : public input_filter { +public: + unix2dos_input_filter() : has_linefeed_(false) { } + + template + int get(Source& src) + { + if (has_linefeed_) { + has_linefeed_ = false; + return '\n'; + } + + int c; + if ((c = iostreams::get(src)) == '\n') { + has_linefeed_ = true; + return '\r'; + } + + return c; + } + + template + void close(Source&) { has_linefeed_ = false; } +private: + bool has_linefeed_; +}; + +class unix2dos_output_filter : public output_filter { +public: + unix2dos_output_filter() : has_linefeed_(false) { } + + template + bool put(Sink& dest, int c) + { + if (c == '\n') + return has_linefeed_ ? + put_char(dest, '\n') : + put_char(dest, '\r') ? + this->put(dest, '\n') : + false; + return iostreams::put(dest, c); + } + + template + void close(Sink&) { has_linefeed_ = false; } +private: + template + bool put_char(Sink& dest, int c) + { + bool result; + if (result = iostreams::put(dest, c)) { + has_linefeed_ = + c == '\r' ? + true : + c == '\n' ? + false : + has_linefeed_; + } + return result; + } + + bool has_linefeed_; +}; + +} } } // End namespaces example, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_UNIX2DOS_FILTER_FILTER_HPP_INCLUDED