// boost/io/quoted_manip.hpp ---------------------------------------------------------// | |
// Copyright Beman Dawes 2010 | |
// Distributed under the Boost Software License, Version 1.0. | |
// See http://www.boost.org/LICENSE_1_0.txt | |
// Library home page http://www.boost.org/libs/io | |
//--------------------------------------------------------------------------------------// | |
#ifndef BOOST_IO_QUOTED_MANIP | |
#define BOOST_IO_QUOTED_MANIP | |
#include <iosfwd> | |
#include <ios> | |
#include <string> | |
#include <iterator> | |
#include <boost/io/ios_state.hpp> | |
namespace boost | |
{ | |
namespace io | |
{ | |
namespace detail { template <class String, class Char> struct quoted_proxy; } | |
// ------------ public interface ------------------------------------------------// | |
// manipulator for const std::basic_string& | |
template <class Char, class Traits, class Alloc> | |
detail::quoted_proxy<std::basic_string<Char, Traits, Alloc> const &, Char> | |
quoted(const std::basic_string<Char, Traits, Alloc>& s, | |
Char escape='\\', Char delim='\"'); | |
// manipulator for non-const std::basic_string& | |
template <class Char, class Traits, class Alloc> | |
detail::quoted_proxy<std::basic_string<Char, Traits, Alloc> &, Char> | |
quoted(std::basic_string<Char, Traits, Alloc>& s, | |
Char escape='\\', Char delim='\"'); | |
// manipulator for const C-string* | |
template <class Char> | |
detail::quoted_proxy<const Char*, Char> | |
quoted(const Char* s, Char escape='\\', Char delim='\"'); | |
// ----------- implementation details -------------------------------------------// | |
namespace detail | |
{ | |
// proxy used as an argument pack | |
template <class String, class Char> | |
struct quoted_proxy | |
{ | |
String string; | |
Char escape; | |
Char delim; | |
quoted_proxy(String s_, Char escape_, Char delim_) | |
: string(s_), escape(escape_), delim(delim_) {} | |
private: | |
// String may be a const type, so disable the assignment operator | |
quoted_proxy& operator=(const quoted_proxy&); // = deleted | |
}; | |
// abstract away difference between proxies with const or non-const basic_strings | |
template <class Char, class Traits, class Alloc> | |
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) | |
{ | |
os << delim; | |
typename std::basic_string<Char, Traits, Alloc>::const_iterator | |
end_it = string.end(); | |
for (typename std::basic_string<Char, Traits, Alloc>::const_iterator | |
it = string.begin(); | |
it != end_it; | |
++it ) | |
{ | |
if (*it == delim || *it == escape) | |
os << escape; | |
os << *it; | |
} | |
os << delim; | |
return os; | |
} | |
// inserter for const std::basic_string& proxies | |
template <class Char, class Traits, class Alloc> | |
inline | |
std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os, | |
const quoted_proxy<std::basic_string<Char, Traits, Alloc> const &, Char>& proxy) | |
{ | |
return basic_string_inserter_imp(os, proxy.string, proxy.escape, proxy.delim); | |
} | |
// inserter for non-const std::basic_string& proxies | |
template <class Char, class Traits, class Alloc> | |
inline | |
std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os, | |
const quoted_proxy<std::basic_string<Char, Traits, Alloc>&, Char>& proxy) | |
{ | |
return basic_string_inserter_imp(os, proxy.string, proxy.escape, proxy.delim); | |
} | |
// inserter for const C-string* proxies | |
template <class Char, class Traits> | |
std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os, | |
const quoted_proxy<const Char*, Char>& proxy) | |
{ | |
os << proxy.delim; | |
for (const Char* it = proxy.string; | |
*it; | |
++it ) | |
{ | |
if (*it == proxy.delim || *it == proxy.escape) | |
os << proxy.escape; | |
os << *it; | |
} | |
os << proxy.delim; | |
return os; | |
} | |
// extractor for non-const std::basic_string& proxies | |
template <class Char, class Traits, class Alloc> | |
std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& is, | |
const quoted_proxy<std::basic_string<Char, Traits, Alloc>&, Char>& proxy) | |
{ | |
proxy.string.clear(); | |
Char c; | |
is >> c; | |
if (c != proxy.delim) | |
{ | |
is.unget(); | |
is >> proxy.string; | |
return is; | |
} | |
{ | |
boost::io::ios_flags_saver ifs(is); | |
is >> std::noskipws; | |
for (;;) | |
{ | |
is >> c; | |
if (!is.good()) // cope with I/O errors or end-of-file | |
break; | |
if (c == proxy.escape) | |
{ | |
is >> c; | |
if (!is.good()) // cope with I/O errors or end-of-file | |
break; | |
} | |
else if (c == proxy.delim) | |
break; | |
proxy.string += c; | |
} | |
} | |
return is; | |
} | |
} // namespace detail | |
// manipulator implementation for const std::basic_string& | |
template <class Char, class Traits, class Alloc> | |
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) | |
{ | |
return detail::quoted_proxy<std::basic_string<Char, Traits, Alloc> const &, Char> | |
(s, escape, delim); | |
} | |
// manipulator implementation for non-const std::basic_string& | |
template <class Char, class Traits, class Alloc> | |
inline detail::quoted_proxy<std::basic_string<Char, Traits, Alloc> &, Char> | |
quoted(std::basic_string<Char, Traits, Alloc>& s, Char escape, Char delim) | |
{ | |
return detail::quoted_proxy<std::basic_string<Char, Traits, Alloc>&, Char> | |
(s, escape, delim); | |
} | |
// manipulator implementation for const C-string* | |
template <class Char> | |
inline detail::quoted_proxy<const Char*, Char> | |
quoted(const Char* s, Char escape, Char delim) | |
{ | |
return detail::quoted_proxy<const Char*, Char> (s, escape, delim); | |
} | |
} // namespace io | |
} // namespace boost | |
#endif // BOOST_IO_QUOTED_MANIP |