]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // boost/io/quoted_manip.hpp ---------------------------------------------------------// |
2 | ||
3 | // Copyright Beman Dawes 2010 | |
4 | ||
5 | // Distributed under the Boost Software License, Version 1.0. | |
6 | // See http://www.boost.org/LICENSE_1_0.txt | |
7 | ||
8 | // Library home page http://www.boost.org/libs/io | |
9 | ||
10 | //--------------------------------------------------------------------------------------// | |
11 | ||
12 | #ifndef BOOST_IO_QUOTED_MANIP | |
13 | #define BOOST_IO_QUOTED_MANIP | |
14 | ||
15 | #include <iosfwd> | |
16 | #include <ios> | |
17 | #include <string> | |
18 | #include <iterator> | |
19 | #include <boost/io/ios_state.hpp> | |
20 | ||
21 | namespace boost | |
22 | { | |
23 | namespace io | |
24 | { | |
25 | namespace detail { template <class String, class Char> struct quoted_proxy; } | |
26 | ||
27 | // ------------ public interface ------------------------------------------------// | |
28 | ||
29 | // manipulator for const std::basic_string& | |
30 | template <class Char, class Traits, class Alloc> | |
31 | detail::quoted_proxy<std::basic_string<Char, Traits, Alloc> const &, Char> | |
32 | quoted(const std::basic_string<Char, Traits, Alloc>& s, | |
33 | Char escape='\\', Char delim='\"'); | |
34 | ||
35 | // manipulator for non-const std::basic_string& | |
36 | template <class Char, class Traits, class Alloc> | |
37 | detail::quoted_proxy<std::basic_string<Char, Traits, Alloc> &, Char> | |
38 | quoted(std::basic_string<Char, Traits, Alloc>& s, | |
39 | Char escape='\\', Char delim='\"'); | |
40 | ||
41 | // manipulator for const C-string* | |
42 | template <class Char> | |
43 | detail::quoted_proxy<const Char*, Char> | |
44 | quoted(const Char* s, Char escape='\\', Char delim='\"'); | |
45 | ||
46 | // ----------- implementation details -------------------------------------------// | |
47 | ||
48 | namespace detail | |
49 | { | |
50 | // proxy used as an argument pack | |
51 | template <class String, class Char> | |
52 | struct quoted_proxy | |
53 | { | |
54 | String string; | |
55 | Char escape; | |
56 | Char delim; | |
57 | ||
58 | quoted_proxy(String s_, Char escape_, Char delim_) | |
59 | : string(s_), escape(escape_), delim(delim_) {} | |
60 | private: | |
61 | // String may be a const type, so disable the assignment operator | |
62 | quoted_proxy& operator=(const quoted_proxy&); // = deleted | |
63 | }; | |
64 | ||
65 | // abstract away difference between proxies with const or non-const basic_strings | |
66 | template <class Char, class Traits, class Alloc> | |
67 | std::basic_ostream<Char, Traits>& | |
68 | basic_string_inserter_imp(std::basic_ostream<Char, Traits>& os, | |
69 | std::basic_string<Char, Traits, Alloc> const & string, Char escape, Char delim) | |
70 | { | |
71 | os << delim; | |
72 | typename std::basic_string<Char, Traits, Alloc>::const_iterator | |
73 | end_it = string.end(); | |
74 | for (typename std::basic_string<Char, Traits, Alloc>::const_iterator | |
75 | it = string.begin(); | |
76 | it != end_it; | |
77 | ++it ) | |
78 | { | |
79 | if (*it == delim || *it == escape) | |
80 | os << escape; | |
81 | os << *it; | |
82 | } | |
83 | os << delim; | |
84 | return os; | |
85 | } | |
86 | ||
87 | // inserter for const std::basic_string& proxies | |
88 | template <class Char, class Traits, class Alloc> | |
89 | inline | |
90 | std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os, | |
91 | const quoted_proxy<std::basic_string<Char, Traits, Alloc> const &, Char>& proxy) | |
92 | { | |
93 | return basic_string_inserter_imp(os, proxy.string, proxy.escape, proxy.delim); | |
94 | } | |
95 | ||
96 | // inserter for non-const std::basic_string& proxies | |
97 | template <class Char, class Traits, class Alloc> | |
98 | inline | |
99 | std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os, | |
100 | const quoted_proxy<std::basic_string<Char, Traits, Alloc>&, Char>& proxy) | |
101 | { | |
102 | return basic_string_inserter_imp(os, proxy.string, proxy.escape, proxy.delim); | |
103 | } | |
104 | ||
105 | // inserter for const C-string* proxies | |
106 | template <class Char, class Traits> | |
107 | std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os, | |
108 | const quoted_proxy<const Char*, Char>& proxy) | |
109 | { | |
110 | os << proxy.delim; | |
111 | for (const Char* it = proxy.string; | |
112 | *it; | |
113 | ++it ) | |
114 | { | |
115 | if (*it == proxy.delim || *it == proxy.escape) | |
116 | os << proxy.escape; | |
117 | os << *it; | |
118 | } | |
119 | os << proxy.delim; | |
120 | return os; | |
121 | } | |
122 | ||
123 | // extractor for non-const std::basic_string& proxies | |
124 | template <class Char, class Traits, class Alloc> | |
125 | std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& is, | |
126 | const quoted_proxy<std::basic_string<Char, Traits, Alloc>&, Char>& proxy) | |
127 | { | |
128 | proxy.string.clear(); | |
129 | Char c; | |
130 | is >> c; | |
131 | if (c != proxy.delim) | |
132 | { | |
133 | is.unget(); | |
134 | is >> proxy.string; | |
135 | return is; | |
136 | } | |
137 | { | |
138 | boost::io::ios_flags_saver ifs(is); | |
139 | is >> std::noskipws; | |
140 | for (;;) | |
141 | { | |
142 | is >> c; | |
143 | if (!is.good()) // cope with I/O errors or end-of-file | |
144 | break; | |
145 | if (c == proxy.escape) | |
146 | { | |
147 | is >> c; | |
148 | if (!is.good()) // cope with I/O errors or end-of-file | |
149 | break; | |
150 | } | |
151 | else if (c == proxy.delim) | |
152 | break; | |
153 | proxy.string += c; | |
154 | } | |
155 | } | |
156 | return is; | |
157 | } | |
158 | ||
159 | } // namespace detail | |
160 | ||
161 | // manipulator implementation for const std::basic_string& | |
162 | template <class Char, class Traits, class Alloc> | |
163 | inline detail::quoted_proxy<std::basic_string<Char, Traits, Alloc> const &, Char> | |
164 | quoted(const std::basic_string<Char, Traits, Alloc>& s, Char escape, Char delim) | |
165 | { | |
166 | return detail::quoted_proxy<std::basic_string<Char, Traits, Alloc> const &, Char> | |
167 | (s, escape, delim); | |
168 | } | |
169 | ||
170 | // manipulator implementation for non-const std::basic_string& | |
171 | template <class Char, class Traits, class Alloc> | |
172 | inline detail::quoted_proxy<std::basic_string<Char, Traits, Alloc> &, Char> | |
173 | quoted(std::basic_string<Char, Traits, Alloc>& s, Char escape, Char delim) | |
174 | { | |
175 | return detail::quoted_proxy<std::basic_string<Char, Traits, Alloc>&, Char> | |
176 | (s, escape, delim); | |
177 | } | |
178 | ||
179 | // manipulator implementation for const C-string* | |
180 | template <class Char> | |
181 | inline detail::quoted_proxy<const Char*, Char> | |
182 | quoted(const Char* s, Char escape, Char delim) | |
183 | { | |
184 | return detail::quoted_proxy<const Char*, Char> (s, escape, delim); | |
185 | } | |
186 | ||
187 | } // namespace io | |
188 | } // namespace boost | |
189 | ||
190 | #endif // BOOST_IO_QUOTED_MANIP |