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
21namespace 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
191