// Streams based on std::span -*- C++ -*-

// Copyright The GNU Toolchain Authors.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/** @file spanstream
 *  This is a Standard C++ Library header.
 */

#ifndef _GLIBCXX_SPANSTREAM
#define _GLIBCXX_SPANSTREAM 1

#pragma GCC system_header

#if __cplusplus > 202002L
#include <span>
#include <streambuf>
#include <istream>
#include <ostream>
#include <bits/ranges_base.h>

#if __cpp_lib_span
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

#define __cpp_lib_spanstream 202106L

template<typename _CharT, typename _Traits = char_traits<_CharT>>
  class basic_spanbuf
  : public basic_streambuf<_CharT, _Traits>
  {
    using __streambuf_type = basic_streambuf<_CharT, _Traits>;

  public:
    using char_type   = _CharT;
    using int_type    = typename _Traits::int_type;
    using pos_type    = typename _Traits::pos_type;
    using off_type    = typename _Traits::off_type;
    using traits_type = _Traits;

    // [spanbuf.ctor], constructors
    basic_spanbuf() : basic_spanbuf(ios_base::in | ios_base::out)
    { }

    explicit
    basic_spanbuf(ios_base::openmode __which)
    : __streambuf_type(), _M_mode(__which)
    { }

    explicit
    basic_spanbuf(std::span<_CharT> __s,
		  ios_base::openmode __which = ios_base::in | ios_base::out)
    : __streambuf_type(), _M_mode(__which)
    { span(__s); }

    basic_spanbuf(const basic_spanbuf&) = delete;

    /** Move constructor.
     *
     * Transfers the buffer and pointers into the get and put areas from
     * `__rhs` to `*this`.
     *
     * In this implementation `rhs` is left unchanged,
     * but that is not guaranteed by the standard.
     */
    basic_spanbuf(basic_spanbuf&& __rhs)
    : __streambuf_type(__rhs), _M_mode(__rhs._M_mode), _M_buf(__rhs._M_buf)
    { }

    // [spanbuf.assign], assignment and swap
    basic_spanbuf& operator=(const basic_spanbuf&) = delete;

    basic_spanbuf&
    operator=(basic_spanbuf&& __rhs)
    {
      basic_spanbuf(std::move(__rhs)).swap(*this);
      return *this;
    }

    void
    swap(basic_spanbuf& __rhs)
    {
      __streambuf_type::swap(__rhs);
      std::swap(_M_mode, __rhs._M_mode);
      std::swap(_M_buf, __rhs._M_buf);
    }

    // [spanbuf.members], member functions
    std::span<_CharT>
    span() const noexcept
    {
      if (_M_mode & ios_base::out)
	return {this->pbase(), this->pptr()};
      else
	return _M_buf;
    }

    void
    span(std::span<_CharT> __s) noexcept
    {
      _M_buf = __s;
      if (_M_mode & ios_base::out)
	{
	  this->setp(__s.data(), __s.data() + __s.size());
	  if (_M_mode & ios_base::ate)
	    this->pbump(__s.size());
	}
      if (_M_mode & ios_base::in)
	this->setg(__s.data(), __s.data(), __s.data() + __s.size());
    }

  protected:
    // [spanbuf.virtuals], overridden virtual functions
    basic_streambuf<_CharT, _Traits>*
    setbuf(_CharT* __s, streamsize __n) override
    {
      span({__s, __n});
      return this;
    }

    pos_type
    seekoff(off_type __off, ios_base::seekdir __way,
	    ios_base::openmode __which = ios_base::in | ios_base::out) override
    {
      pos_type __ret =  pos_type(off_type(-1));

      if (__way == ios_base::beg)
	{
	  if (0 <= __off && __off <= _M_buf.size())
	    {
	      if (__which & ios_base::in)
		this->setg(this->eback(), this->eback() + __off, this->egptr());

	      if (__which & ios_base::out)
		{
		  this->setp(this->pbase(), this->epptr());
		  this->pbump(__off);
		}

	      __ret = pos_type(__off);
	    }
	}
      else
	{
	  off_type __base;
	  __which &= (ios_base::in|ios_base::out);

	  if (__which == ios_base::out)
	    __base = this->pptr() - this->pbase();
	  else if (__way == ios_base::cur)
	    {
	      if (__which == ios_base::in)
		__base = this->gptr() - this->eback();
	      else
		return __ret;
	    }
	  else if (__way == ios_base::end)
	    __base = _M_buf.size();

	  if (__builtin_add_overflow(__base, __off, &__off))
	    return __ret;

	  if (__off < 0 || __off > _M_buf.size())
	    return __ret;

	  if (__which & ios_base::in)
	    this->setg(this->eback(), this->eback() + __off, this->egptr());

	  if (__which & ios_base::out)
	    {
	      this->setp(this->pbase(), this->epptr());
	      this->pbump(__off);
	    }

	  __ret = pos_type(__off);

	}
      return __ret;
    }

    pos_type
    seekpos(pos_type __sp,
	    ios_base::openmode __which = ios_base::in | ios_base::out) override
    { return seekoff(off_type(__sp), ios_base::beg, __which); }

  private:

    ios_base::openmode _M_mode;
    std::span<_CharT> _M_buf;
  };

template<typename _CharT, typename _Traits>
  inline void
  swap(basic_spanbuf<_CharT, _Traits>& __x,
       basic_spanbuf<_CharT, _Traits>& __y)
  { __x.swap(__y); }

using spanbuf = basic_spanbuf<char>;
using wspanbuf = basic_spanbuf<wchar_t>;

template<typename _CharT, typename _Traits = char_traits<_CharT>>
  class basic_ispanstream
  : public basic_istream<_CharT, _Traits>
  {
    using __istream_type = basic_istream<_CharT, _Traits>;

  public:
    using char_type   = _CharT;
    using int_type    = typename _Traits::int_type;
    using pos_type    = typename _Traits::pos_type;
    using off_type    = typename _Traits::off_type;
    using traits_type = _Traits;

    // [ispanstream.ctor], constructors
    explicit
    basic_ispanstream(std::span<_CharT> __s,
		      ios_base::openmode __which = ios_base::in)
    : __istream_type(std::__addressof(_M_sb)),
      _M_sb(__s, __which | ios_base::in)
    { }

    basic_ispanstream(const basic_ispanstream&) = delete;

    basic_ispanstream(basic_ispanstream&& __rhs)
    : __istream_type(std::move(__rhs)), _M_sb(std::move(__rhs._M_sb))
    {
      __istream_type::set_rdbuf(std::addressof(_M_sb));
    }

    template<typename _Ros>
      requires ranges::borrowed_range<_Ros>
	&& (!convertible_to<_Ros, std::span<_CharT>>)
	&& convertible_to<_Ros, std::span<const _CharT>>
      explicit
      basic_ispanstream(_Ros&& __s)
      : __istream_type(std::__addressof(_M_sb)),
	_M_sb(ios_base::in)
      {
	std::span<const _CharT> __sp(std::forward<_Ros>(__s));
	_M_sb.span({const_cast<_CharT*>(__sp.data()), __sp.size()});
      }

    // [ispanstream.assign], assignment and swap
    basic_ispanstream& operator=(const basic_ispanstream&) = delete;
    basic_ispanstream& operator=(basic_ispanstream&& __rhs) = default;

    void
    swap(basic_ispanstream& __rhs)
    {
      __istream_type::swap(__rhs);
      _M_sb.swap(__rhs._M_sb);
    }

    // [ispanstream.members], member functions
    basic_spanbuf<_CharT, _Traits>*
    rdbuf() const noexcept
    {
      return const_cast<basic_spanbuf<_CharT, _Traits>*>(std::__addressof(_M_sb));
    }

    std::span<const _CharT>
    span() const noexcept
    { return _M_sb.span(); }

    void
    span(std::span<_CharT> __s) noexcept
    { return _M_sb.span(__s); }

    template<typename _Ros>
      requires ranges::borrowed_range<_Ros>
	&& (!convertible_to<_Ros, std::span<_CharT>>)
	&& convertible_to<_Ros, std::span<const _CharT>>
      void
      span(_Ros&& __s) noexcept
      {
	std::span<const _CharT> __sp(std::forward<_Ros>(__s));
	_M_sb.span({const_cast<_CharT*>(__sp.data()), __sp.size()});
      }

  private:
    basic_spanbuf<_CharT, _Traits> _M_sb;
  };

template<typename _CharT, typename _Traits>
  inline void
  swap(basic_ispanstream<_CharT, _Traits>& __x,
       basic_ispanstream<_CharT, _Traits>& __y)
  { __x.swap(__y); }

using ispanstream = basic_ispanstream<char>;
using wispanstream = basic_ispanstream<wchar_t>;

template<typename _CharT, typename _Traits = char_traits<_CharT>>
  class basic_ospanstream
  : public basic_ostream<_CharT, _Traits>
  {
    using __ostream_type = basic_ostream<_CharT, _Traits>;

  public:
    using char_type   = _CharT;
    using int_type    = typename _Traits::int_type;
    using pos_type    = typename _Traits::pos_type;
    using off_type    = typename _Traits::off_type;
    using traits_type = _Traits;

    // [ospanstream.ctor], constructors
    explicit
    basic_ospanstream(std::span<_CharT> __s,
		      ios_base::openmode __which = ios_base::out)
    : __ostream_type(std::__addressof(_M_sb)),
      _M_sb(__s, __which | ios_base::in)
    { }

    basic_ospanstream(const basic_ospanstream&) = delete;

    basic_ospanstream(basic_ospanstream&& __rhs)
    : __ostream_type(std::move(__rhs)), _M_sb(std::move(__rhs._M_sb))
    {
      __ostream_type::set_rdbuf(std::addressof(_M_sb));
    }

    // [ospanstream.assign], assignment and swap
    basic_ospanstream& operator=(const basic_ospanstream&) = delete;
    basic_ospanstream& operator=(basic_ospanstream&& __rhs) = default;

    void
    swap(basic_ospanstream& __rhs)
    {
      __ostream_type::swap(__rhs);
      _M_sb.swap(__rhs._M_sb);
    }

    // [ospanstream.members], member functions
    basic_spanbuf<_CharT, _Traits>*
    rdbuf() const noexcept
    {
      return const_cast<basic_spanbuf<_CharT, _Traits>*>(std::__addressof(_M_sb));
    }

    std::span<_CharT>
    span() const noexcept
    { return _M_sb.span(); }

    void
    span(std::span<_CharT> __s) noexcept
    { return _M_sb.span(__s); }

  private:
    basic_spanbuf<_CharT, _Traits> _M_sb;
  };

template<typename _CharT, typename _Traits>
  inline void
  swap(basic_ospanstream<_CharT, _Traits>& __x,
       basic_ospanstream<_CharT, _Traits>& __y)
  { __x.swap(__y); }

using ospanstream = basic_ospanstream<char>;
using wospanstream = basic_ospanstream<wchar_t>;

template<typename _CharT, typename _Traits = char_traits<_CharT>>
  class basic_spanstream
  : public basic_iostream<_CharT, _Traits>
  {
    using __iostream_type = basic_iostream<_CharT, _Traits>;

  public:
    using char_type   = _CharT;
    using int_type    = typename _Traits::int_type;
    using pos_type    = typename _Traits::pos_type;
    using off_type    = typename _Traits::off_type;
    using traits_type = _Traits;

    // [spanstream.ctor], constructors
    explicit
    basic_spanstream(std::span<_CharT> __s,
		     ios_base::openmode __which = ios_base::out | ios_base::in)
    : __iostream_type(std::__addressof(_M_sb)),
      _M_sb(__s, __which)
    { }

    basic_spanstream(const basic_spanstream&) = delete;

    basic_spanstream(basic_spanstream&& __rhs)
    : __iostream_type(std::move(__rhs)), _M_sb(std::move(__rhs._M_sb))
    {
      __iostream_type::set_rdbuf(std::addressof(_M_sb));
    }

    // [spanstream.assign], assignment and swap
    basic_spanstream& operator=(const basic_spanstream&) = delete;
    basic_spanstream& operator=(basic_spanstream&& __rhs) = default;

    void
    swap(basic_spanstream& __rhs)
    {
      __iostream_type::swap(__rhs);
      _M_sb.swap(__rhs._M_sb);
    }

    // [spanstream.members], members
    basic_spanbuf<_CharT, _Traits>*
    rdbuf() const noexcept
    {
      return const_cast<basic_spanbuf<_CharT, _Traits>*>(std::__addressof(_M_sb));
    }

    std::span<_CharT>
    span() const noexcept
    { return _M_sb.span(); }

    void
    span(std::span<_CharT> __s) noexcept
    { return _M_sb.span(__s); }

  private:
    basic_spanbuf<_CharT, _Traits> _M_sb;
  };

template<typename _CharT, typename _Traits>
  inline void
  swap(basic_spanstream<_CharT, _Traits>& __x,
       basic_spanstream<_CharT, _Traits>& __y)
  { __x.swap(__y); }

using spanstream = basic_spanstream<char>;
using wspanstream = basic_spanstream<wchar_t>;

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // __cpp_lib_span
#endif // C++23
#endif // _GLIBCXX_SPANSTREAM
