<!DOCTYPE html>

<html>
<head>
    <meta charset="utf-8">
    <title>Buffer Sequence Adaptors</title>
    <style type="text/css">
    body
    {
        font-size: 10pt;
        font-family: sans-serif;
    }
    code
    {
        display: block;
        white-space: pre;
        margin-top: -1.00em;
        margin-left: 2.0em;
    }
    p
    {
        text-align: justify
    }
    p > code
    {
        margin-top: initial;
        margin-left: initial;
    }
    li {
        text-align: justify
    }
    ol.p
    {
        margin-left: -2.0em;
    }
    blockquote.note
    {
        background-color:#E0E0E0;
        padding-left: 15px;
        padding-right: 15px;
        padding-top: 1px;
        padding-bottom: 1px;
    }
    p.note
    {
        background-color:#E0E0E0;
        padding-left: 15px;
        padding-right: 15px;
        padding-top: 1px;
        padding-bottom: 1px;
    }
    ins { background-color: #CCFFCC; }
    del { background-color: #FFCCCC; }
    .insert { background-color: #CCFFCC; }
    address {text-align:right;}
    h1 {text-align:center;}
    span.comment {color:#C80000;}
    </style>
</head>
<body>
<pre>
Doc. no:  P1145R0
Audience: LEWG
Date:     2018-07-09
Reply-To: Vinnie Falco (<a href="mailto:vinnie.falco@gmail.com">vinnie.falco@gmail.com</a>)
</pre>
<hr>
<h1>Buffer Sequence Adaptors</h1>



<h2>Contents</h2>
<ol>
<li><a href="#overview">Overview</a></li>
<li><a href="#motivation">Motivation and Scope</a></li>
<li><a href="#impact">Impact On the Standard</a></li>
<li><a href="#design">Design Decisions</a></li>
<li><a href="#wording">Proposed Wording</a></li>
<li><a href="#acknowledgements">Acknowledgements</a></li>
</ol>

<!----------------------------------------------------------------------------->

<h2 id="overview">1. Overview</h2>
<p>
This document proposes additional algorithms and types for working with
the buffer sequence concepts defined in [networking.ts].
</p>

<!----------------------------------------------------------------------------->

<h2 id="motivation">2. Motivation and Scope</h2>
<p>
[networking.ts] defines a buffer sequence as a bidirectional range of
non-owning references to individual contiguous memory regions. The adaptors
and types proposed in this paper allow for simply lazy transformations
of buffer sequences to achieve effects commonly used in implementations
which operate on buffers.
</p>

<h3 id="motivation.target">2.1 Target Audience</h3>
<p>
The algorithms and types provided here are aimed squarely at developers
working with [networking.ts].
</p>

<h3 id="motivation.reference">2.2 Reference Implementation</h3>
<p>
The Boost.Beast library, from portions of which this proposal is derived,
has been deployed in a number of production systems, such as internet-facing
HTTP servers, decentralized cryptocurrency networks, and finance applications.
The Boost.Beast library has been used on the following platforms:
</p>
<ul>
<li>Win32 using Visual Studio 14 and 15</li>
<li>Linux (newer kernels) using g++ 4.8 or later</li>
<li>Mac OS X 10.4 using clang 3.6 or later</li>
</ul>

<h3 id="motivation.related">2.3 Related Work</h3>
<p>
The interfaces used for transacting with buffer sequences are based on
idioms established in [networking.ts].
library.
</p>

<!----------------------------------------------------------------------------->

<h2 id="impact">3. Impact On the Standard</h2>
<p>
This is a pure library proposal. It does not add any new language features,
nor does it alter any existing standard library headers. This library can be
implemented using compilers that conform to the C++17 standard. However, the
library also requires [networking.ts].
</p>

<!----------------------------------------------------------------------------->

<h2 id="design">4. Design Decisions</h2>
<p>
The prefix <tt>buffers_</tt> was chosen because buffer sequences can contain
multiple memory regions. This distinguishes the algorithms from those functions
which operate on types meeting the requirements of <em>DynamicBuffer</em>, which
use the prefix <tt>buffer_</tt> (these algorithms are present in Boost.Beast but
not proposed here).
</p>
<p>
The types <tt>buffers_cat_view</tt> and <tt>buffers_prefix_view</tt> are made
public so that callers can build abstractions which refer to the type. The
ranges produced by the library are simple adaptors over existing memory buffers
with reference semantics. Memory allocations are not required in the implementation.
</p>

<!----------------------------------------------------------------------------->

<h2 id="wording">5. Proposed Wording (informative)</h2>

<p>Exact wording is to be determined after [networking.ts] is merged</p>

<h3>5.1 Definitions</h3>
<ol>

<li><p>The following definitions are adopted from [networking.ts] as-is:</p>
    <ul>
    <li>Types <tt>const_buffer</tt> and <tt>mutable_buffer</tt>.</li>
    <li>Concepts <em>ConstBufferSequence</em> and <em>MutableBufferSequence</em>.</li>
    <li>The functions <tt>buffer_size</tt>, <tt>buffer_sequence_begin</tt>, and <tt>buffer_sequence_end</tt>.</li>
    <li>Class templates <tt>is_const_buffer_sequence_v</tt> and <tt>is_mutable_buffer_sequence_v</tt>.</li>
    </ul></li>

<li><p>Define <tt><em>BUFFER_TYPE</em>(TN...)</tt> as follows:</p>
    <ul>
    <li>The type <tt>mutable_buffer</tt> if <tt>(... && is_mutable_buffer_sequence_v&lt;TN&gt;)</tt> is true, otherwise
    <li>The type <tt>const_buffer</tt>.</li>
    </ul>
    <p class=note>[Note] possible implementation
        <code>
template &lt;class... TN&gt;
using BUFFER_TYPE = conditional_t&lt;
    (... &amp;&amp; is_mutable_buffer_sequence_v&lt;TN&gt;), mutable_buffer, const_buffer&gt;;
</code>
    </p>
    </li>

</ol>

<h3>5.2 Header <tt>&lt;experimental/buffer&gt;</tt> additions</h3>
<code>
namespace std {
namespace experimental {
namespace net {

template &lt;class... BN&gt;
class buffers_cat_view;

template &lt;class BS&gt;
class buffers_prefix_view;

template &lt;class BS&gt;
class buffers_suffix;

template &lt;class... BN&gt;
auto buffers_cat(BN const&amp;... buffers) -> buffers_cat_view &lt;BN...&gt;;

template &lt;class BS&gt;
auto buffers_front (BS const&amp; buffers) -> <em>see-below</em>;

auto buffers_prefix (size_t size, const_buffer buffer) -> const_buffer;
auto buffers_prefix (size_t size, mutable_buffer buffer) -> mutable_buffer;

template &lt;class BS&gt;
auto buffers_prefix (size_t size, BS const&amp; buffers) -> buffers_prefix_view &lt;BS&gt;;

} // net
} // experimental
} // std
</code>

<!----------------------------------------------------------------------------->

<h3>5.3 Class template <tt>buffers_cat_view</tt></h3>
<p>This class represents the buffer sequence created when a variable number of
    existing buffer sequences of possibly dissimilar types are concatenated in
    order, with empty buffers in the underlying sequences removed when at least
    one sequence is present.</p>
<code>
namespace std {
namespace experimental {
namespace net {

template &lt;class... BN&gt;
class buffers_cat_view
{
    tuple &lt;BN...&gt; bn_; // <em>exposition only</em>

public:
    using value_type = <em>see-below</em>;

    using const_iterator = <em>see-below</em>;

    explicit buffers_cat_view (BN const&amp;... buffers);

    buffers_cat_view (buffers_cat_view const&amp; other);

    const_iterator begin() const noexcept;
    const_iterator end() const noexcept;
};

} // net
} // experimental
} // std
</code>
<ol>

<li><p><code>using value_type = <em>see-below</em></code></p>
    <p><em>Type:</em> <tt><em>BUFFER_TYPE</em>(BN...)</tt></p></li>

<li><p>Class template <tt>buffers_cat_view</tt> satisfies <em>ConstBufferSequence</em>.
    If <tt>value_type</tt> is <tt>mutable_buffer</tt>, then <tt>buffers_cat_view</tt>
    also satisfies <em>MutableBufferSequence</em>.
    Template argument <tt>BN</tt> requires that <tt>sizeof...(BN) > 0</tt> and
    that <tt>(... && is_const_buffer_sequence_v&lt;BN&gt;)</tt> is true.</p></li>

<li><p><code>using const_iterator = <em>see-below</em></code></p>
    <p>An iterator which satisfies all the requirements for bidirectional
    iterators (C++ 2014 [bidirectional.iterators]) except that:</p>
    <ul>
    <li>The <tt>reference</tt> type is the same as <tt>buffers_cat_view::value_type</tt>, and
    <li>There is no requirement to provide <tt>operator-&gt;</tt>.</li>
    </ul></li>

<li><p><code>explicit buffers_cat_view (BN const&amp;... buffers)</code></p>
    <p><em>Effects:</em> Constructs a buffer sequence which when iterated
    represents the concatenation of the sequences in <tt>buffers</tt>, except
    that memory regions of size zero are not visited. The implementation shall
    maintain a copy of each value in <tt>buffers</tt> until the view is
    destroyed</p></li>

<li><p><code>buffers_cat_view (buffers_cat_view const&amp; other)</code></p>
    <p><em>Effects:</em> Constructs a copy of <tt>other</tt>.</p></li>

<li><p><code>const_iterator begin() const noexcept</code></p>
    <p><em>Returns:</em> An iterator pointing to first buffer in the view which
    does not have a zero size, otherwise returns <tt>this->end()</tt>.</p></li>

<li><p><code>const_iterator end() const noexcept</code></p>
    <p><em>Returns:</em> An iterator pointing to one past the last buffer in
    the view which does not have a zero size.</p></li>

</ol>

<!----------------------------------------------------------------------------->

<h3>5.4 Class template <tt>buffers_prefix_view</tt></h3>
<p>This class represents the buffer sequence created by forming the prefix of
    an existing buffer sequence.</p>
<code>
template &lt;class BS&gt;
class buffers_prefix_view
{
    BS bs_; // <em>exposition only</em>

public:
    using value_type = <em>see-below</em>;

    using const_iterator = <em>see-below</em>;

    buffers_prefix_view (size_t size, BS const&amp; buffers);

    template &lt;class... Args&gt;
    buffers_prefix_view (size_t size, in_place_t, Args&amp;&amp;... args);

    buffers_prefix_view (buffers_prefix_view const&amp; other);

    const_iterator begin() const noexcept;
    const_iterator end() const noexcept;
};
</code>
<ol>

<li><p><code>using value_type = <em>see-below</em></code></p>
    <p><em>Type:</em> <tt><em>BUFFER_TYPE</em>(BS)</tt></p></li>

<li><p>Class template <tt>buffers_prefix_view</tt> satisfies <em>ConstBufferSequence</em>.
    If <tt>value_type</tt> is <tt>mutable_buffer</tt>, then <tt>buffers_prefix_view</tt>
    also satisfies <em>MutableBufferSequence</em>.
    Template argument <tt>BS</tt> satisfies <em>ConstBufferSequence</em></p></li>

<li><p><code>using const_iterator = <em>see-below</em></code></p>
    <p>An iterator which satisfies all the requirements for bidirectional
    iterators (C++ 2014 [bidirectional.iterators]) except that:</p>
    <ul>
    <li>The <tt>reference</tt> type is the same as <tt>buffers_prefix_view::value_type</tt>, and
    <li>There is no requirement to provide <tt>operator-&gt;</tt>.</li>
    </ul></li>

<li><p><code>buffers_prefix_view (size_t size, BS const&amp; buffers)</code></p>
    <p><em>Effects:</em> Constructs a buffer sequence which when iterated
    represents a prefix of <tt>buffers</tt> with size <tt>min(size, buffer_size(buffers))</tt>.
    The implementation shall maintain a copy of <tt>buffers</tt> until the
    view is destroyed.</p></li>

<li><p><code>template &lt;class... Args&gt;
buffers_prefix_view (size_t size, in_place_t, Args&amp;&amp;... args)</code></p>
    <p><em>Effects:</em> Constructs a buffer sequence which when iterated,
    represents a prefix of the buffer sequence <tt>b</tt> formed by <tt>BS(forward&lt;Args&gt;(Args)...)</tt>,
    with size <tt>min(size, buffer_size(buffers))</tt>. The implementation shall
    maintain a copy of <tt>b</tt> until the view is destroyed.</p></li>

<li><p><code>buffers_prefix_view (buffers_prefix_view const&amp; other)</code></p>
    <p><em>Effects:</em> Constructs a copy of <tt>other</tt>.</p></li>

<li><p><code>const_iterator begin() const noexcept</code></p>
    <p><em>Returns:</em> An iterator pointing to the beginning of the buffer
    sequence.</p></li>

<li><p><code>const_iterator end() const noexcept</code></p>
    <p><em>Returns:</em> An iterator pointing to one past the end of the
    buffer sequence.</p></li>

</ol>

<!----------------------------------------------------------------------------->

<h3>5.5 Class <tt>buffers_suffix</tt></h3>
<p>This class template represents the buffer sequence created by forming
    a suffix of an existing buffer sequence. A member function allows the
    caller to decrease the length of the suffix by a specified amount.</p>
<code>
template &lt;class BS&gt;
class buffers_suffix
{
    BS bs_; // <em>exposition only</em>

public:
    using value_type = <em>see-below</em>;

    using const_iterator = <em>see-below</em>;

    explicit buffers_suffix (BS const&amp; buffers);

    template &lt;class... Args&gt;
    buffers_suffix (in_place_t, Args&amp;&amp;... args);

    buffers_suffix (buffers_suffix const&amp; other);

    void consume (size_t amount) noexcept;

    const_iterator begin() const noexcept;

    const_iterator end() const noexcept;
};
</code>
<ol>

<li><p><code>using value_type = <em>see-below</em></code></p>
    <p><em>Type:</em> <tt><em>BUFFER_TYPE</em>(BS)</tt></p></li>

<li><p>Class template <tt>buffers_suffix</tt> satisfies <em>ConstBufferSequence</em>.
    If <tt>value_type</tt> is <tt>mutable_buffer</tt>, then <tt>buffers_suffix</tt>
    also satisfies <em>MutableBufferSequence</em>.
    Template argument <tt>BS</tt> satisfies <em>ConstBufferSequence</em></p></li>

<li><p><code>using const_iterator = <em>see-below</em></code></p>
    <p>An iterator which satisfies all the requirements for bidirectional
    iterators (C++ 2014 [bidirectional.iterators]) except that:</p>
    <ul>
    <li>The <tt>reference</tt> type is the same as <tt>buffers_suffix::value_type</tt>, and
    <li>There is no requirement to provide <tt>operator-&gt;</tt>.</li>
    </ul></li>

<li><p><code>buffers_suffix (BS const&amp; buffers)</code></p>
    <p><em>Effects:</em> Constructs a buffer sequence which when
    iterated represents a suffix of <tt>buffers</tt> with size equal to
    <tt>buffer_size(buffers)</tt>.
    The implementation shall maintain a copy of <tt>buffers</tt> until the
    buffer sequence is destroyed.</p></li>

<li><p><code>template &lt;class... Args&gt;
buffers_suffix (size_t size, in_place_t, Args&amp;&amp;... args)</code></p>
    <p><em>Effects:</em> Constructs a buffer sequence which when iterated,
    represents a suffix of the buffer sequence <tt>b</tt> formed by
    <tt>BS(forward&lt;Args&gt;(Args)...)</tt>, with size equal to
    <tt>buffer_size(b)</tt>.
    The implementation shall maintain a copy of <tt>b</tt> until the
    view is destroyed.</p></li>

<li><p><code>buffers_suffix (buffers_suffix const&amp; other)</code></p>
    <p><em>Effects:</em> Constructs a copy of <tt>other</tt>.</p></li>

<li><p><code>void consume (size_t amount) noexcept</code></p>
    <p><em>Effects:</em> Reduces the size of the suffix by <tt>amount</tt>.
    If <tt>amount</tt> is greater than or equal to the current size of the
    suffix, the resulting size of the suffix will become zero.</p></li>

<li><p><code>const_iterator begin() const noexcept</code></p>
    <p><em>Returns:</em> An iterator pointing to the beginning of the buffer
    sequence.</p></li>

<li><p><code>const_iterator end() const noexcept</code></p>
    <p><em>Returns:</em> An iterator pointing to one past the end of the
    buffer sequence.</p></li>

</ol>

<!----------------------------------------------------------------------------->

<h3>5.6 Function <tt>buffers_cat</tt></h3>
<p>This function returns a view representing a buffer sequence which, when
    iterated, produces the concatenation of the passed buffer sequences.</p>
<code>
template &lt;class... BN&gt;
auto buffers_cat(BN const&amp;... buffers) -> buffers_cat_view &lt;BN...&gt;;
</code>
<ol>

<li><p><em>Requires:</em> <tt>sizeof...(BN) &gt; 0</tt> and
    <tt>(... && is_const_buffer_sequence_v&lt;BN&gt;)</tt> is true.</p></li>

<li><p><em>Returns:</em> <tt>buffers_cat_view&lt;BN&gt;(buffers)</tt>.</p></li>

</ol>

<!----------------------------------------------------------------------------->

<h3>5.7 Function <tt>buffers_prefix</tt></h3>
<p>This function returns a buffer sequence representing a prefix
    of the passed buffer sequence.</p>
<code>
auto buffers_prefix (size_t size, const_buffer buffer) -> const_buffer;

auto buffers_prefix (size_t size, mutable_buffer buffer) -> mutable_buffer;

template &lt;class BS&gt;
auto buffers_prefix (size_t size, BS const&amp; buffers) -> buffers_prefix_view &lt;BS&gt;;
</code>
<ol>

<li><p><code>const_buffer buffers_prefix (size_t size, const_buffer buffer)</code></p>
    <p><em>Returns:</em> <tt>const_buffer (buffer.data(), min(size, buffer.size()))</tt>.</p></li>

<li><p><code>mutable_buffer buffers_prefix (size_t size, mutable_buffer buffer)</code></p>
    <p><em>Returns:</em> <tt>mutable_buffer (buffer.data(), min(size, buffer.size()))</tt>.</p></li>

<li><p><code>template &lt;class BS&gt;
buffers_prefix_view &lt;BS&gt;
buffers_prefix (size_t size, BS const&amp; buffers);</code></p>
    <p><em>Requires:</em> <tt>BS</tt> satisfies <em>ConstBufferSequence</em>.</p>
    <p><em>Returns:</em> <tt>buffers_prefix_view (buffers)</tt>.</p>
    <p><em>Note:</em> This function participates in overload resolution only when:</p>
    <ul>
    <li><tt>is_same_v&lt;BS, const_buffer&gt;</tt> is false,</li>
    <li><tt>is_same_v&lt;BS, mutable_buffer&gt;</tt> is false, and</li>
    <li><tt>is_const_buffer_sequence_v&lt;BS&gt;</tt> is true.</li>
    </ul></li>

</ol>

<!----------------------------------------------------------------------------->

<h3>5.8 Function <tt>buffers_front</tt></h3>
<p>This function returns the first buffer in a buffer sequence, or an empty
    buffer if the buffer sequence is an empty range.</p>
<code>
template &lt;class BS&gt;
auto buffers_front (BS const&amp; buffers) -> <em>see-below</em>;
</code>
<ol>

<li><p><em>Requires:</em> <tt>BS</tt> satisfies <em>ConstBufferSequence</em>.</p></li>

<li><p><em>Type:</em> The return type is <tt>decltype(buffer_sequence_begin(buffers))::const_iterator::value_type</tt>.</p></li>

<li><p><em>Returns:</em> If <tt>buffer_sequence_begin(buffers) != buffer_sequence_end(buffers)</tt> then
    the return value is constructed from <tt>*buffer_sequence_begin(buffers)</tt>, otherwise the return
    value is default-constructed.
    </p></li>

</ol>
<!----------------------------------------------------------------------------->

<h2 id="#acknowledgements">Acknowledgements</h2>
<p>
Many thanks to Agustín Bergé for showing me the ropes with some of the wording.
</p>

</body>
