123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- /*
- 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 <boost/io/detail/buffer_fill.hpp>
- #include <boost/io/detail/ostream_guard.hpp>
- #include <boost/io/ios_state.hpp>
- namespace boost {
- namespace io {
- namespace detail {
- template<class String, class Char>
- struct quoted_proxy {
- String string;
- Char escape;
- Char delim;
- };
- template<class Char>
- struct quoted_state {
- const Char* string;
- std::size_t size;
- std::size_t count;
- };
- template<class Char>
- inline quoted_state<Char>
- 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<Char> state = { string,
- static_cast<std::size_t>(end - string), count };
- return state;
- }
- template<class Char, class String>
- inline quoted_state<Char>
- 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<Char> state = { begin, size, count };
- return state;
- }
- template<class Char, class Traits>
- inline bool
- quoted_put(std::basic_streambuf<Char, Traits>& 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<std::size_t>(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<class Char, class Traits, class String>
- inline std::basic_ostream<Char, Traits>&
- quoted_out(std::basic_ostream<Char, Traits>& os, String* string, Char escape,
- Char delim)
- {
- typedef std::basic_ostream<Char, Traits> stream;
- ostream_guard<Char, Traits> guard(os);
- typename stream::sentry entry(os);
- if (entry) {
- quoted_state<Char> state = boost::io::detail::quoted_start(string,
- escape, delim);
- std::basic_streambuf<Char, Traits>& buf = *os.rdbuf();
- std::size_t width = static_cast<std::size_t>(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<class Char, class Traits>
- inline std::basic_ostream<Char, Traits>&
- operator<<(std::basic_ostream<Char, Traits>& os,
- const quoted_proxy<const Char*, Char>& proxy)
- {
- return boost::io::detail::quoted_out(os, proxy.string, proxy.escape,
- proxy.delim);
- }
- template <class Char, class Traits, class Alloc>
- inline std::basic_ostream<Char, Traits>&
- operator<<(std::basic_ostream<Char, Traits>& os,
- const quoted_proxy<const std::basic_string<Char, Traits, Alloc>*,
- Char>& proxy)
- {
- return boost::io::detail::quoted_out(os, proxy.string, proxy.escape,
- proxy.delim);
- }
- 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 boost::io::detail::quoted_out(os, proxy.string, proxy.escape,
- proxy.delim);
- }
- template<class Char, class Traits, class Alloc>
- inline std::basic_istream<Char, Traits>&
- operator>>(std::basic_istream<Char, Traits>& is,
- const quoted_proxy<std::basic_string<Char, Traits, Alloc>*, 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<class Char, class Traits, class Alloc>
- inline detail::quoted_proxy<const std::basic_string<Char, Traits, Alloc>*,
- Char>
- quoted(const std::basic_string<Char, Traits, Alloc>& s, Char escape='\\',
- Char delim='\"')
- {
- detail::quoted_proxy<const std::basic_string<Char, Traits, Alloc>*,
- Char> proxy = { &s, escape, delim };
- return proxy;
- }
- 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='\"')
- {
- detail::quoted_proxy<std::basic_string<Char, Traits, Alloc>*,
- Char> proxy = { &s, escape, delim };
- return proxy;
- }
- template<class Char>
- inline detail::quoted_proxy<const Char*, Char>
- quoted(const Char* s, Char escape='\\', Char delim='\"')
- {
- detail::quoted_proxy<const Char*, Char> proxy = { s, escape, delim };
- return proxy;
- }
- } /* io */
- } /* boost */
- #endif
|