// 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 #include #include #include #include namespace boost { namespace io { namespace detail { template struct quoted_proxy; } // ------------ public interface ------------------------------------------------// // manipulator for const std::basic_string& template detail::quoted_proxy const &, Char> quoted(const std::basic_string& s, Char escape=(Char)'\\', Char delim=(Char)'\"'); // manipulator for non-const std::basic_string& template detail::quoted_proxy &, Char> quoted(std::basic_string& s, Char escape=(Char)'\\', Char delim=(Char)'\"'); // manipulator for const C-string* template detail::quoted_proxy quoted(const Char* s, Char escape=(Char)'\\', Char delim=(Char)'\"'); // ----------- implementation details -------------------------------------------// namespace detail { // proxy used as an argument pack template 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 std::basic_ostream& basic_string_inserter_imp(std::basic_ostream& os, std::basic_string const & string, Char escape, Char delim) { os << delim; typename std::basic_string::const_iterator end_it = string.end(); for (typename std::basic_string::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 inline std::basic_ostream& operator<<(std::basic_ostream& os, const quoted_proxy const &, Char>& proxy) { return basic_string_inserter_imp(os, proxy.string, proxy.escape, proxy.delim); } // inserter for non-const std::basic_string& proxies template inline std::basic_ostream& operator<<(std::basic_ostream& os, const quoted_proxy&, Char>& proxy) { return basic_string_inserter_imp(os, proxy.string, proxy.escape, proxy.delim); } // inserter for const C-string* proxies template std::basic_ostream& operator<<(std::basic_ostream& os, const quoted_proxy& 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 std::basic_istream& operator>>(std::basic_istream& is, const quoted_proxy&, 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 inline detail::quoted_proxy const &, Char> quoted(const std::basic_string& s, Char escape, Char delim) { return detail::quoted_proxy const &, Char> (s, escape, delim); } // manipulator implementation for non-const std::basic_string& template inline detail::quoted_proxy &, Char> quoted(std::basic_string& s, Char escape, Char delim) { return detail::quoted_proxy&, Char> (s, escape, delim); } // manipulator implementation for const C-string* template inline detail::quoted_proxy quoted(const Char* s, Char escape, Char delim) { return detail::quoted_proxy (s, escape, delim); } } // namespace io } // namespace boost #endif // BOOST_IO_QUOTED_MANIP