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 pdalboost 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 quoted_proxypdalboost::io::detail::quoted_proxy58 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>& basic_string_inserter_imp(std::basic_ostream<Char,Traits> & os,std::basic_string<Char,Traits,Alloc> const & string,Char escape,Char delim)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 operator <<(std::basic_ostream<Char,Traits> & os,const quoted_proxy<std::basic_string<Char,Traits,Alloc> const &,Char> & proxy)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 operator <<(std::basic_ostream<Char,Traits> & os,const quoted_proxy<std::basic_string<Char,Traits,Alloc> &,Char> & proxy)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> operator <<(std::basic_ostream<Char,Traits> & os,const quoted_proxy<const Char *,Char> & proxy)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> operator >>(std::basic_istream<Char,Traits> & is,const quoted_proxy<std::basic_string<Char,Traits,Alloc> &,Char> & proxy)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 pdalboost::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> quoted(const std::basic_string<Char,Traits,Alloc> & s,Char escape,Char delim)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> quoted(std::basic_string<Char,Traits,Alloc> & s,Char escape,Char delim)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> quoted(const Char * s,Char escape,Char delim)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 pdalboost 189 190 #endif // BOOST_IO_QUOTED_MANIP 191