dictionary_filter.hpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
  2. // (C) Copyright 2003-2007 Jonathan Turkanis
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
  5. // See http://www.boost.org/libs/iostreams for documentation.
  6. #ifndef BOOST_IOSTREAMS_DICTIONARY_FILTER_HPP_INCLUDED
  7. #define BOOST_IOSTREAMS_DICTIONARY_FILTER_HPP_INCLUDED
  8. #include <algorithm> // swap.
  9. #include <cassert>
  10. #include <cstdio> // EOF.
  11. #include <iostream> // cin, cout.
  12. #include <cctype>
  13. #include <map>
  14. #include <boost/config.hpp> // BOOST_NO_STDC_NAMESPACE.
  15. #include <boost/iostreams/concepts.hpp>
  16. #include <boost/iostreams/filter/stdio.hpp>
  17. #include <boost/iostreams/operations.hpp>
  18. #ifdef BOOST_NO_STDC_NAMESPACE
  19. namespace std {
  20. using ::isalpha;
  21. using ::isupper;
  22. using ::toupper;
  23. using ::tolower;
  24. }
  25. #endif
  26. namespace boost { namespace iostreams { namespace example {
  27. class dictionary {
  28. public:
  29. void add(std::string key, const std::string& value);
  30. void replace(std::string& key);
  31. private:
  32. typedef std::map<std::string, std::string> map_type;
  33. void tolower(std::string& str);
  34. map_type map_;
  35. };
  36. class dictionary_stdio_filter : public stdio_filter {
  37. public:
  38. dictionary_stdio_filter(dictionary& d) : dictionary_(d) { }
  39. private:
  40. void do_filter()
  41. {
  42. using namespace std;
  43. while (true) {
  44. int c = std::cin.get();
  45. if (c == EOF || !std::isalpha((unsigned char) c)) {
  46. dictionary_.replace(current_word_);
  47. cout.write( current_word_.data(),
  48. static_cast<std::streamsize>(current_word_.size()) );
  49. current_word_.erase();
  50. if (c == EOF)
  51. break;
  52. cout.put(c);
  53. } else {
  54. current_word_ += c;
  55. }
  56. }
  57. }
  58. dictionary& dictionary_;
  59. std::string current_word_;
  60. };
  61. class dictionary_input_filter : public input_filter {
  62. public:
  63. dictionary_input_filter(dictionary& d)
  64. : dictionary_(d), off_(std::string::npos), eof_(false)
  65. { }
  66. template<typename Source>
  67. int get(Source& src)
  68. {
  69. // Handle unfinished business.
  70. if (off_ != std::string::npos && off_ < current_word_.size())
  71. return current_word_[off_++];
  72. if (off_ == current_word_.size()) {
  73. current_word_.erase();
  74. off_ = std::string::npos;
  75. }
  76. if (eof_)
  77. return EOF;
  78. // Compute curent word.
  79. while (true) {
  80. int c;
  81. if ((c = iostreams::get(src)) == WOULD_BLOCK)
  82. return WOULD_BLOCK;
  83. if (c == EOF || !std::isalpha((unsigned char) c)) {
  84. dictionary_.replace(current_word_);
  85. off_ = 0;
  86. if (c == EOF)
  87. eof_ = true;
  88. else
  89. current_word_ += c;
  90. break;
  91. } else {
  92. current_word_ += c;
  93. }
  94. }
  95. return this->get(src); // Note: current_word_ is not empty.
  96. }
  97. template<typename Source>
  98. void close(Source&)
  99. {
  100. current_word_.erase();
  101. off_ = std::string::npos;
  102. eof_ = false;
  103. }
  104. private:
  105. dictionary& dictionary_;
  106. std::string current_word_;
  107. std::string::size_type off_;
  108. bool eof_;
  109. };
  110. class dictionary_output_filter : public output_filter {
  111. public:
  112. typedef std::map<std::string, std::string> map_type;
  113. dictionary_output_filter(dictionary& d)
  114. : dictionary_(d), off_(std::string::npos)
  115. { }
  116. template<typename Sink>
  117. bool put(Sink& dest, int c)
  118. {
  119. if (off_ != std::string::npos && !write_current_word(dest))
  120. return false;
  121. if (!std::isalpha((unsigned char) c)) {
  122. dictionary_.replace(current_word_);
  123. off_ = 0;
  124. }
  125. current_word_ += c;
  126. return true;
  127. }
  128. template<typename Sink>
  129. void close(Sink& dest)
  130. {
  131. // Reset current_word_ and off_, saving old values.
  132. std::string current_word;
  133. std::string::size_type off = 0;
  134. current_word.swap(current_word_);
  135. std::swap(off, off_);
  136. // Write remaining characters to dest.
  137. if (off == std::string::npos) {
  138. dictionary_.replace(current_word);
  139. off = 0;
  140. }
  141. if (!current_word.empty())
  142. iostreams::write(
  143. dest,
  144. current_word.data() + off,
  145. static_cast<std::streamsize>(current_word.size() - off)
  146. );
  147. }
  148. private:
  149. template<typename Sink>
  150. bool write_current_word(Sink& dest)
  151. {
  152. using namespace std;
  153. std::streamsize amt =
  154. static_cast<std::streamsize>(current_word_.size() - off_);
  155. std::streamsize result =
  156. iostreams::write(dest, current_word_.data() + off_, amt);
  157. if (result == amt) {
  158. current_word_.erase();
  159. off_ = string::npos;
  160. return true;
  161. } else {
  162. off_ += static_cast<string::size_type>(result);
  163. return false;
  164. }
  165. }
  166. dictionary& dictionary_;
  167. std::string current_word_;
  168. std::string::size_type off_;
  169. };
  170. //------------------Implementation of dictionary------------------------------//
  171. inline void dictionary::add(std::string key, const std::string& value)
  172. {
  173. tolower(key);
  174. map_[key] = value;
  175. }
  176. inline void dictionary::replace(std::string& key)
  177. {
  178. using namespace std;
  179. string copy(key);
  180. tolower(copy);
  181. map_type::iterator it = map_.find(key);
  182. if (it == map_.end())
  183. return;
  184. string& value = it->second;
  185. if (!value.empty() && !key.empty() && std::isupper((unsigned char) key[0]))
  186. value[0] = std::toupper((unsigned char) value[0]);
  187. key = value;
  188. return;
  189. }
  190. inline void dictionary::tolower(std::string& str)
  191. {
  192. for (std::string::size_type z = 0, len = str.size(); z < len; ++z)
  193. str[z] = std::tolower((unsigned char) str[z]);
  194. }
  195. } } } // End namespaces example, iostreams, boost.
  196. #endif // #ifndef BOOST_IOSTREAMS_DICTIONARY_FILTER_HPP_INCLUDED