1/*
2Copyright 2010 Beman Dawes
3
4Copyright 2019-2020 Glen Joseph Fernandes
5(glenjofe@gmail.com)
6
7Distributed under the Boost Software License, Version 1.0.
8(http://www.boost.org/LICENSE_1_0.txt)
9*/
10#ifndef BOOST_IO_QUOTED_HPP
11#define BOOST_IO_QUOTED_HPP
12
13#include <boost/io/detail/buffer_fill.hpp>
14#include <boost/io/detail/ostream_guard.hpp>
15#include <boost/io/ios_state.hpp>
16
17namespace boost {
18namespace io {
19namespace detail {
20
21template<class String, class Char>
22struct quoted_proxy {
23 String string;
24 Char escape;
25 Char delim;
26};
27
28template<class Char>
29struct quoted_state {
30 const Char* string;
31 std::size_t size;
32 std::size_t count;
33};
34
35template<class Char>
36inline quoted_state<Char>
37quoted_start(const Char* string, Char escape, Char delim)
38{
39 const Char* end = string;
40 std::size_t count = 2;
41 for (Char ch; (ch = *end) != 0; ++end) {
42 count += 1 + (ch == escape || ch == delim);
43 }
44 quoted_state<Char> state = { string,
45 static_cast<std::size_t>(end - string), count };
46 return state;
47}
48
49template<class Char, class String>
50inline quoted_state<Char>
51quoted_start(const String* string, Char escape, Char delim)
52{
53 const Char* begin = string->data();
54 std::size_t size = string->size();
55 std::size_t count = 2;
56 for (const Char *it = begin, *end = begin + size; it != end; ++it) {
57 Char ch = *it;
58 count += 1 + (ch == escape || ch == delim);
59 }
60 quoted_state<Char> state = { begin, size, count };
61 return state;
62}
63
64template<class Char, class Traits>
65inline bool
66quoted_put(std::basic_streambuf<Char, Traits>& buf, const Char* string,
67 std::size_t size, std::size_t count, Char escape, Char delim)
68{
69 if (buf.sputc(delim) == Traits::eof()) {
70 return false;
71 }
72 if (size == count) {
73 if (static_cast<std::size_t>(buf.sputn(string, size)) != size) {
74 return false;
75 }
76 } else {
77 for (const Char* end = string + size; string != end; ++string) {
78 Char ch = *string;
79 if ((ch == escape || ch == delim) &&
80 buf.sputc(escape) == Traits::eof()) {
81 return false;
82 }
83 if (buf.sputc(ch) == Traits::eof()) {
84 return false;
85 }
86 }
87 }
88 return buf.sputc(delim) != Traits::eof();
89}
90
91template<class Char, class Traits, class String>
92inline std::basic_ostream<Char, Traits>&
93quoted_out(std::basic_ostream<Char, Traits>& os, String* string, Char escape,
94 Char delim)
95{
96 typedef std::basic_ostream<Char, Traits> stream;
97 ostream_guard<Char, Traits> guard(os);
98 typename stream::sentry entry(os);
99 if (entry) {
100 quoted_state<Char> state = boost::io::detail::quoted_start(string,
101 escape, delim);
102 std::basic_streambuf<Char, Traits>& buf = *os.rdbuf();
103 std::size_t width = static_cast<std::size_t>(os.width());
104 if (width <= state.count) {
105 if (!boost::io::detail::quoted_put(buf, state.string, state.size,
106 state.count, escape, delim)) {
107 return os;
108 }
109 } else if ((os.flags() & stream::adjustfield) == stream::left) {
110 if (!boost::io::detail::quoted_put(buf, state.string, state.size,
111 state.count, escape, delim) ||
112 !boost::io::detail::buffer_fill(buf, os.fill(),
113 width - state.count)) {
114 return os;
115 }
116 } else if (!boost::io::detail::buffer_fill(buf, os.fill(),
117 width - state.count) ||
118 !boost::io::detail::quoted_put(buf, state.string, state.size,
119 state.count, escape, delim)) {
120 return os;
121 }
122 os.width(0);
123 }
124 guard.release();
125 return os;
126}
127
128template<class Char, class Traits>
129inline std::basic_ostream<Char, Traits>&
130operator<<(std::basic_ostream<Char, Traits>& os,
131 const quoted_proxy<const Char*, Char>& proxy)
132{
133 return boost::io::detail::quoted_out(os, proxy.string, proxy.escape,
134 proxy.delim);
135}
136
137template <class Char, class Traits, class Alloc>
138inline std::basic_ostream<Char, Traits>&
139operator<<(std::basic_ostream<Char, Traits>& os,
140 const quoted_proxy<const std::basic_string<Char, Traits, Alloc>*,
141 Char>& proxy)
142{
143 return boost::io::detail::quoted_out(os, proxy.string, proxy.escape,
144 proxy.delim);
145}
146
147template<class Char, class Traits, class Alloc>
148inline std::basic_ostream<Char, Traits>&
149operator<<(std::basic_ostream<Char, Traits>& os,
150 const quoted_proxy<std::basic_string<Char, Traits, Alloc>*, Char>& proxy)
151{
152 return boost::io::detail::quoted_out(os, proxy.string, proxy.escape,
153 proxy.delim);
154}
155
156template<class Char, class Traits, class Alloc>
157inline std::basic_istream<Char, Traits>&
158operator>>(std::basic_istream<Char, Traits>& is,
159 const quoted_proxy<std::basic_string<Char, Traits, Alloc>*, Char>& proxy)
160{
161 Char ch;
162 if (!(is >> ch)) {
163 return is;
164 }
165 if (ch != proxy.delim) {
166 is.unget();
167 return is >> *proxy.string;
168 }
169 {
170 boost::io::ios_flags_saver ifs(is);
171 std::noskipws(base&: is);
172 proxy.string->clear();
173 while ((is >> ch) && ch != proxy.delim) {
174 if (ch == proxy.escape && !(is >> ch)) {
175 break;
176 }
177 proxy.string->push_back(ch);
178 }
179 }
180 return is;
181}
182
183} /* detail */
184
185template<class Char, class Traits, class Alloc>
186inline detail::quoted_proxy<const std::basic_string<Char, Traits, Alloc>*,
187 Char>
188quoted(const std::basic_string<Char, Traits, Alloc>& s, Char escape='\\',
189 Char delim='\"')
190{
191 detail::quoted_proxy<const std::basic_string<Char, Traits, Alloc>*,
192 Char> proxy = { &s, escape, delim };
193 return proxy;
194}
195
196template<class Char, class Traits, class Alloc>
197inline detail::quoted_proxy<std::basic_string<Char, Traits, Alloc>*, Char>
198quoted(std::basic_string<Char, Traits, Alloc>& s, Char escape='\\',
199 Char delim='\"')
200{
201 detail::quoted_proxy<std::basic_string<Char, Traits, Alloc>*,
202 Char> proxy = { &s, escape, delim };
203 return proxy;
204}
205
206template<class Char>
207inline detail::quoted_proxy<const Char*, Char>
208quoted(const Char* s, Char escape='\\', Char delim='\"')
209{
210 detail::quoted_proxy<const Char*, Char> proxy = { s, escape, delim };
211 return proxy;
212}
213
214} /* io */
215} /* boost */
216
217#endif
218

source code of boost/libs/io/include/boost/io/quoted.hpp