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