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)'\\', Char delim=(Char)'\"');
|
---|
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)'\\', Char delim=(Char)'\"');
|
---|
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)'\\', Char delim=(Char)'\"');
|
---|
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
|
---|