Line data Source code
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 0 : 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 0 : 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 0 : os << delim;
72 : typename std::basic_string<Char, Traits, Alloc>::const_iterator
73 0 : end_it = string.end();
74 0 : for (typename std::basic_string<Char, Traits, Alloc>::const_iterator
75 0 : it = string.begin();
76 0 : it != end_it;
77 0 : ++it )
78 : {
79 0 : if (*it == delim || *it == escape)
80 0 : os << escape;
81 0 : os << *it;
82 : }
83 0 : os << delim;
84 0 : return os;
85 : }
86 :
87 : // inserter for const std::basic_string& proxies
88 : template <class Char, class Traits, class Alloc>
89 : inline
90 0 : 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 0 : 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 0 : 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 0 : (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
|