123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
- // (C) Copyright 2003-2007 Jonathan Turkanis
- // 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 <algorithm> // swap.
- #include <cassert>
- #include <cstdio> // EOF.
- #include <iostream> // cin, cout.
- #include <cctype>
- #include <map>
- #include <boost/config.hpp> // BOOST_NO_STDC_NAMESPACE.
- #include <boost/iostreams/concepts.hpp>
- #include <boost/iostreams/filter/stdio.hpp>
- #include <boost/iostreams/operations.hpp>
- #ifdef BOOST_NO_STDC_NAMESPACE
- namespace std {
- using ::isalpha;
- using ::isupper;
- using ::toupper;
- using ::tolower;
- }
- #endif
- namespace boost { namespace iostreams { namespace example {
- class dictionary {
- public:
- void add(std::string key, const std::string& value);
- void replace(std::string& key);
- private:
- typedef std::map<std::string, std::string> map_type;
- void tolower(std::string& str);
- map_type map_;
- };
- 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((unsigned char) c)) {
- dictionary_.replace(current_word_);
- cout.write( current_word_.data(),
- static_cast<std::streamsize>(current_word_.size()) );
- current_word_.erase();
- 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<typename Source>
- int get(Source& src)
- {
- // Handle unfinished business.
- if (off_ != std::string::npos && off_ < current_word_.size())
- return current_word_[off_++];
- if (off_ == current_word_.size()) {
- current_word_.erase();
- off_ = std::string::npos;
- }
- if (eof_)
- return EOF;
- // Compute curent word.
- while (true) {
- int c;
- if ((c = iostreams::get(src)) == WOULD_BLOCK)
- return WOULD_BLOCK;
- if (c == EOF || !std::isalpha((unsigned char) c)) {
- 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<typename Source>
- void close(Source&)
- {
- current_word_.erase();
- 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<std::string, std::string> map_type;
- dictionary_output_filter(dictionary& d)
- : dictionary_(d), off_(std::string::npos)
- { }
- template<typename Sink>
- bool put(Sink& dest, int c)
- {
- if (off_ != std::string::npos && !write_current_word(dest))
- return false;
- if (!std::isalpha((unsigned char) c)) {
- dictionary_.replace(current_word_);
- off_ = 0;
- }
- current_word_ += c;
- return true;
- }
- template<typename Sink>
- void close(Sink& dest)
- {
- // Reset current_word_ and off_, saving old values.
- std::string current_word;
- std::string::size_type off = 0;
- current_word.swap(current_word_);
- std::swap(off, off_);
- // Write remaining characters to dest.
- if (off == std::string::npos) {
- dictionary_.replace(current_word);
- off = 0;
- }
- if (!current_word.empty())
- iostreams::write(
- dest,
- current_word.data() + off,
- static_cast<std::streamsize>(current_word.size() - off)
- );
- }
- private:
- template<typename Sink>
- bool write_current_word(Sink& dest)
- {
- using namespace std;
- std::streamsize amt =
- static_cast<std::streamsize>(current_word_.size() - off_);
- std::streamsize result =
- iostreams::write(dest, current_word_.data() + off_, amt);
- if (result == amt) {
- current_word_.erase();
- off_ = string::npos;
- return true;
- } else {
- off_ += static_cast<string::size_type>(result);
- return false;
- }
- }
- dictionary& dictionary_;
- std::string current_word_;
- std::string::size_type off_;
- };
- //------------------Implementation of dictionary------------------------------//
- inline void dictionary::add(std::string key, const std::string& value)
- {
- tolower(key);
- map_[key] = value;
- }
- inline void 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;
- string& value = it->second;
- if (!value.empty() && !key.empty() && std::isupper((unsigned char) key[0]))
- value[0] = std::toupper((unsigned char) value[0]);
- key = value;
- return;
- }
- inline void dictionary::tolower(std::string& str)
- {
- for (std::string::size_type z = 0, len = str.size(); z < len; ++z)
- str[z] = std::tolower((unsigned char) str[z]);
- }
- } } } // End namespaces example, iostreams, boost.
- #endif // #ifndef BOOST_IOSTREAMS_DICTIONARY_FILTER_HPP_INCLUDED
|