mirror of
https://github.com/boostorg/io.git
synced 2025-07-29 20:07:13 +02:00
Support stream width and fill and write directly to stream buffer
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
/*
|
||||
Copyright 2010 Beman Dawes
|
||||
|
||||
Copyright 2019 Glen Joseph Fernandes
|
||||
Copyright 2019-2020 Glen Joseph Fernandes
|
||||
(glenjofe@gmail.com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
@ -10,10 +10,9 @@ Distributed under the Boost Software License, Version 1.0.
|
||||
#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>
|
||||
#include <ios>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
namespace io {
|
||||
@ -26,37 +25,113 @@ struct quoted_proxy {
|
||||
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)
|
||||
{
|
||||
os.put(proxy.delim);
|
||||
for (const Char* it = proxy.string; *it; ++it) {
|
||||
if (*it == proxy.delim || *it == proxy.escape) {
|
||||
os.put(proxy.escape);
|
||||
}
|
||||
os.put(*it);
|
||||
}
|
||||
return os.put(proxy.delim);
|
||||
}
|
||||
|
||||
template<class Char, class Traits, class Alloc>
|
||||
inline std::basic_ostream<Char, Traits>&
|
||||
quoted_output(std::basic_ostream<Char, Traits>& os,
|
||||
const std::basic_string<Char, Traits, Alloc>& string, Char escape,
|
||||
Char delim)
|
||||
{
|
||||
os.put(delim);
|
||||
for (typename std::basic_string<Char, Traits,
|
||||
Alloc>::const_iterator it = string.begin(), end = string.end();
|
||||
it != end; ++it) {
|
||||
if (*it == delim || *it == escape) {
|
||||
os.put(escape);
|
||||
}
|
||||
os.put(*it);
|
||||
}
|
||||
return os.put(delim);
|
||||
return boost::io::detail::quoted_out(os, proxy.string, proxy.escape,
|
||||
proxy.delim);
|
||||
}
|
||||
|
||||
template <class Char, class Traits, class Alloc>
|
||||
@ -65,7 +140,7 @@ operator<<(std::basic_ostream<Char, Traits>& os,
|
||||
const quoted_proxy<const std::basic_string<Char, Traits, Alloc>*,
|
||||
Char>& proxy)
|
||||
{
|
||||
return boost::io::detail::quoted_output(os, *proxy.string, proxy.escape,
|
||||
return boost::io::detail::quoted_out(os, proxy.string, proxy.escape,
|
||||
proxy.delim);
|
||||
}
|
||||
|
||||
@ -74,7 +149,7 @@ 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_output(os, *proxy.string, proxy.escape,
|
||||
return boost::io::detail::quoted_out(os, proxy.string, proxy.escape,
|
||||
proxy.delim);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user