| 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
|
|---|