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

source code of boost/libs/iostreams/example/dictionary_filter.hpp