/* Copyright 2010 Beman Dawes Copyright 2019-2020 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #ifndef BOOST_IO_QUOTED_HPP #define BOOST_IO_QUOTED_HPP #include #include #include namespace boost { namespace io { namespace detail { template struct quoted_proxy { String string; Char escape; Char delim; }; template struct quoted_state { const Char* string; std::size_t size; std::size_t count; }; template inline quoted_state quoted_start(const Char* string, Char escape, Char delim) { const Char* end = string; std::size_t count = 2; for (Char ch; (ch = *end) != 0; ++end) { count += 1 + (ch == escape || ch == delim); } quoted_state state = { string, static_cast(end - string), count }; return state; } template inline quoted_state quoted_start(const String* string, Char escape, Char delim) { const Char* begin = string->data(); std::size_t size = string->size(); std::size_t count = 2; for (const Char *it = begin, *end = begin + size; it != end; ++it) { Char ch = *it; count += 1 + (ch == escape || ch == delim); } quoted_state state = { begin, size, count }; return state; } template inline bool quoted_put(std::basic_streambuf& buf, const Char* string, std::size_t size, std::size_t count, Char escape, Char delim) { if (buf.sputc(delim) == Traits::eof()) { return false; } if (size == count) { if (static_cast(buf.sputn(string, size)) != size) { return false; } } else { for (const Char* end = string + size; string != end; ++string) { Char ch = *string; if ((ch == escape || ch == delim) && buf.sputc(escape) == Traits::eof()) { return false; } if (buf.sputc(ch) == Traits::eof()) { return false; } } } return buf.sputc(delim) != Traits::eof(); } template inline std::basic_ostream& quoted_out(std::basic_ostream& os, String* string, Char escape, Char delim) { typedef std::basic_ostream stream; ostream_guard guard(os); typename stream::sentry entry(os); if (entry) { quoted_state state = boost::io::detail::quoted_start(string, escape, delim); std::basic_streambuf& buf = *os.rdbuf(); std::size_t width = static_cast(os.width()); if (width <= state.count) { if (!boost::io::detail::quoted_put(buf, state.string, state.size, state.count, escape, delim)) { return os; } } else if ((os.flags() & stream::adjustfield) == stream::left) { if (!boost::io::detail::quoted_put(buf, state.string, state.size, state.count, escape, delim) || !boost::io::detail::buffer_fill(buf, os.fill(), width - state.count)) { return os; } } else if (!boost::io::detail::buffer_fill(buf, os.fill(), width - state.count) || !boost::io::detail::quoted_put(buf, state.string, state.size, state.count, escape, delim)) { return os; } os.width(0); } guard.release(); return os; } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const quoted_proxy& proxy) { return boost::io::detail::quoted_out(os, proxy.string, proxy.escape, proxy.delim); } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const quoted_proxy*, Char>& proxy) { return boost::io::detail::quoted_out(os, proxy.string, proxy.escape, proxy.delim); } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const quoted_proxy*, Char>& proxy) { return boost::io::detail::quoted_out(os, proxy.string, proxy.escape, proxy.delim); } template inline std::basic_istream& operator>>(std::basic_istream& is, const quoted_proxy*, Char>& proxy) { Char ch; if (!(is >> ch)) { return is; } if (ch != proxy.delim) { is.unget(); return is >> *proxy.string; } { boost::io::ios_flags_saver ifs(is); std::noskipws(is); proxy.string->clear(); while ((is >> ch) && ch != proxy.delim) { if (ch == proxy.escape && !(is >> ch)) { break; } proxy.string->push_back(ch); } } return is; } } /* detail */ template inline detail::quoted_proxy*, Char> quoted(const std::basic_string& s, Char escape='\\', Char delim='\"') { detail::quoted_proxy*, Char> proxy = { &s, escape, delim }; return proxy; } template inline detail::quoted_proxy*, Char> quoted(std::basic_string& s, Char escape='\\', Char delim='\"') { detail::quoted_proxy*, Char> proxy = { &s, escape, delim }; return proxy; } template inline detail::quoted_proxy quoted(const Char* s, Char escape='\\', Char delim='\"') { detail::quoted_proxy proxy = { s, escape, delim }; return proxy; } } /* io */ } /* boost */ #endif