namespace strf {

template <typename CharT>
constexpr std::size_t min_size_after_recycle();

template <typename CharT>
class basic_outbuff
{ /* ... */ };

template <typename CharT>
class basic_outbuff_noexcept: public basic_outbuff<CharT>
{ /* ... */ };

template <typename CharT>
void put(basic_outbuff<CharT>& ob, CharT c);

template <typename CharT>
class basic_cstr_writer final: public basic_outbuff_noexcept<CharT>
{ /* ... */};

template <typename CharT>
class discarded_outbuff final: public basic_outbuff_noexcept<CharT>
{ /* ... */};

template <typename CharT>
CharT* outbuff_garbage_buf();

template <typename CharT>
CharT* outbuff_garbage_buf_end();

using bin_outbuff     = basic_outbuff<std::byte>;
using u8outbuff       = basic_outbuff<char8_t>;
using outbuff         = basic_outbuff<char>;
using u16outbuff      = basic_outbuff<char16_t>;
using u32outbuff      = basic_outbuff<char32_t>;
using woutbuff        = basic_outbuff<wchar_t>;

using u8cstr_writer  = basic_cstr_writer<char8_t>;
using cstr_writer    = basic_cstr_writer<char>;
using u16cstr_writer = basic_cstr_writer<char16_t>;
using u32cstr_writer = basic_cstr_writer<char32_t>;
using wcstr_writer   = basic_cstr_writer<wchar_t>;

} // namespace strf

1. Function template min_size_after_recycle

template <typename CharT>
constexpr std::size_t min_size_after_recycle();
Return value

Implementation-defined value greater than or equal to 64.

2. Class template basic_outbuff

2.1. Synopsis

namespace strf {

template <typename CharT>
class basic_outbuff;
{
public:

    using char_type = CharT;

    basic_outbuff(const basic_outbuff&) = delete;
    basic_outbuff(basic_outbuff&&) = delete;
    basic_outbuff& operator=(const basic_outbuff&) = delete;
    basic_outbuff& operator=(basic_outbuff&&) = delete;

    virtual ~basic_outbuff() = default;

    CharT* pointer() const noexcept;
    CharT* end() const noexcept;
    std::size_t size() const noexcept;
    bool good() const noexcept;
    void advance_to(CharT* p);
    void advance(std::size_t n);
    void require(std::size_t s);

    virtual bool recycle() = 0;

protected:

    basic_outbuff(CharT* pointer_, CharT* end_);

    basic_outbuff(CharT* pointer_, std::size_t n);

    void set_pointer(CharT* p) noexcept;
    void set_end(CharT* e) noexcept;
    void set_good(bool g) noexcept;
};

// global functions

template <typename CharT>
void put( basic_outbuff<CharT>& ob, CharT ch );

} // namespace strf

2.2. Member types

using char_type = CharT;

2.3. Public member functions

CharT* pointer() const noxcept;
Return

The memory position where the content shall be written.

CharT* end() const noxcept;
Return

The end of memory position where the content shall be written. Dereferencing end() has undefined behaviour.

std::size_t size() const noexcept;
Return

end() - pointer()

virtual void recycle() = 0;
Posconditions
  • size() >= min_size_after_recycle<CharT>()

  • The range [ pointer(), end() ) is valid accessible memory area

  • If the return value of good() was false before this call to recycle(), then good() remains returning false.

void require(std::size_t s)
Effect

Calls recycle() if size() < s.

Precondition

s <= min_size_after_recycle<CharT>()

Postcondition

size() >= s

void advance_to(CharT* p)
Effect

Advance the buffer’s pointer to p.

Precondition

pointer() <= p && p <= end()

Postcondition

pointer() == p

void advance(std::size_t n)
Effect

Same as advance_to(pointer() + n)

Precondition

n <= size()

void advance()
Effect

Same as advance_to(1)

Precondition

pointer() != end()

bool good() const;
Return

The state of this object.

Semantincs

good() == false means that writting anything on pointer(), and calling advance_to and recycle() has no relevant side effect besides their postconditions.

Note

The range [ pointer(), end() ) shall aways be a valid accessible memory, even when good() returns false.

2.4. Protected Member functions

basic_outbuff(CharT* pointer_, CharT* end_)
Preconditions
  • pointer_ <= end_

  • The range [ pointer_, end_ ) must be an accessible memory area.

Posconditions
  • pointer() == pointer_

  • end() == end_

  • good() == true

basic_outbuff(CharT* pointer_, std::size_t n)
Preconditions
  • The range [ pointer_, `pointer_ + n ` ) must be an accessible memory area.

Posconditions
  • pointer() == pointer_

  • end() == pointer_ + n

  • good() == true

void set_pointer(CharT* p) noexcept
Postconditions

pointer() == p

void set_end(CharT* e) noexcept
Postconditions

end() == e

void set_good(bool g) noexcept
Postconditions

good() == g

2.5. Global functions

template <typename CharT>
void put(basic_outbuff<CharT>& ob, CharT ch);
Effect

Same as:

if (ob.size() == 0) {
    ob.recycle();
}
*ob.pointer() = ch;
ob.advance();

3. Class template basic_outbuff_noexcept

namespace strf {

template <typename CharT>
class basic_outbuff_noexcept: public basic_outbuff<CharT>
{
public:

    virtual void recycle() noexcept = 0;

protected:

    using basic_outbuff<CharT>::basic_outbuff;
};

// type aliases

using outbuff_noexcept      = basic_outbuff_noexcept<char>;
using u8outbuff_noexcept    = basic_outbuff_noexcept<char8_t>;
using u16outbuff_noexcept   = basic_outbuff_noexcept<char16_t>;
using u32outbuff_noexcept   = basic_outbuff_noexcept<char32_t>;
using woutbuff_noexcept     = basic_outbuff_noexcept<wchar_t>;
using bin_outbuff_noexcept  = basic_outbuff_noexcept<std::byte>;

} // namespace strf

4. Class template basic_cstr_writer

namespace strf {

template <typename CharT>
class basic_cstr_writer final: public basic_outbuff_noexcept<CharT>
{
public:

    basic_cstr_writer(CharT* dest, CharT* dest_end) noexcept;
    basic_cstr_writer(CharT* dest, std::size_t len) noexcept;
    template <std::size_t N>
    basic_cstr_writer(CharT (&dest)[N]) noexcept;

    void recycle() noexcept override;
    struct result
    {
        CharT* ptr;
        bool truncated;
    };
    result finish() noexcept;
};

} // namespace strf

4.1. Public member function

basic_cstr_writer(CharT* dest, CharT* dest_end) noexcept;
Precondition

dest < dest_end

Postconditions
  • good() == true

  • pointer() == dest

  • end() == dest_end - 1

basic_cstr_writer(CharT* dest, std::size_t dest_size) noexcept;
Precondition

dest_size != 0

Postconditions
  • good() == true

  • pointer() == dest

  • end() == dest + dest_size - 1

template <std::size_t N>
basic_cstr_writer(CharT (&dest)[N]) noexcept;
Postconditions
  • good() == true

  • pointer() == dest

  • end() == dest + N - 1

void recycle() noexcept;
Postconditions
result finish() noexcept;
Effects
  • Assign to '\0' the position after the last written character in memory area used to initialize this object and set this object into "bad" state.

Return value
  • result::truncated is true if recycle or finish has ever been called in this object.

  • result::ptr points to the termination character '\0'.

Postconditions

5. Class template discarded_outbuff

discarded_outbuff it’s the library’s analogous to /dev/null. A discarded_outbuff object ignores anything written to it.

namespace strf {

template <typename CharT>
class discarded_outbuff final: public basic_outbuff_noexcept<CharT>
{
public:
    discarded_outbuff() noexcept;
    void recycle() noexcept override;
};

} // namespace strf
discarded_outbuff() noexcept;
Postconditions
void recycle() noexcept;
Postconditions

6. Garbage buffer

These function templates return the begin and the end of a memory area that is never supposed to be read. It can be used when implementing a class that derives from basic_outbuff to set the buffer when the state is "bad".

template <typename CharT>
CharT* garbage_buf() noexcept;
template <typename CharT>
CharT* garbage_buf_end() noexcept;