// (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 // swap. #include #include // EOF. #include // cin, cout. #include #include #include // BOOST_NO_STDC_NAMESPACE. #include #include #include #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 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(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 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 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 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((unsigned char) c)) { dictionary_.replace(current_word_); off_ = 0; } current_word_ += c; return true; } template 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(current_word.size() - off) ); } private: template bool write_current_word(Sink& dest) { using namespace std; std::streamsize amt = static_cast(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_ += 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