// strstream standard header -*-c++-*-
// Copyright 2009-2017 IAR Systems AB.
#ifndef _STRSTREAM_
#define _STRSTREAM_

#ifndef _SYSTEM_BUILD
  #pragma system_include
#endif

#include <istream>

namespace std {

// CLASS strstreambuf
class strstreambuf
  : public streambuf
{       // stream buffer associated with static or allocated character array
public:
  typedef strstreambuf _Myt;
  typedef streambuf _Mysb;
  enum
  {       // constants for bits in stream state
    _Allocated = 1, // set if character array storage has been allocated
    _Constant = 2,  // set if character array nonmutable
    _Dynamic = 4,   // set if character array length grows on demand
    _Frozen = 8};   // set if character array ownership given away
  typedef int _Strstate;

  explicit strstreambuf(streamsize _Count = 0)
  {       // construct with empty character array, suggested initial size
    _Init(_Count);
  }

  strstreambuf(void *(*_Allocfunc)(size_t),
               void (*_Freefunc)(void *))
  {       // construct with empty character array, allocation functions
    _Init();
    _Palloc = _Allocfunc;
    _Pfree = _Freefunc;
  }

  strstreambuf(char *_Getptr,
               streamsize _Count,
               char *_Putptr = 0)
  {       // construct with [_Getptr, _Getptr + _Count), possibly mutable
    _Init(_Count, _Getptr, _Putptr);
  }

  strstreambuf(const char *_Getptr,
               streamsize _Count)
  {       // construct with [_Getptr, _Getptr + _Count), nonmutable
    _Init(_Count, (char *)_Getptr, 0, _Constant);
  }

  strstreambuf(unsigned char *_Getptr,
               streamsize _Count,
               unsigned char *_Putptr = 0)
  {       // construct with [_Getptr, _Getptr + _Count), possibly mutable
    _Init(_Count, (char *)_Getptr, (char *)_Putptr);
  }

  strstreambuf(const unsigned char *_Getptr,
               streamsize _Count)
  {       // construct with [_Getptr, _Getptr + _Count), nonmutable
    _Init(_Count, (char *)_Getptr, 0, _Constant);
  }

  strstreambuf(_Myt&& _Right)
  {       // construct by moving _Right
    _Init();
    _Assign_rv(std::forward<_Myt>(_Right));
  }

  _Myt& operator=(_Myt&& _Right)
  {       // assign by moving _Right
    _Assign_rv(std::forward<_Myt>(_Right));
    return *this;
  }

  void _Assign_rv(_Myt&& _Right)
  {       // assign by moving _Right
    if (this != &_Right)
    {       // different, worth moving
      _Tidy();
      this->swap(_Right);
    }
  }

  void swap(_Myt& _Right)
  {       // swap with _Right
    if (this != &_Right)
    {       // different, worth swapping
      _Mysb::swap(_Right);
      std::swap(_Minsize, _Right._Minsize);
      std::swap(_Pendsave, _Right._Pendsave);
      std::swap(_Seekhigh, _Right._Seekhigh);
      std::swap(_Strmode, _Right._Strmode);
      std::swap(_Palloc, _Right._Palloc);
      std::swap(_Pfree, _Right._Pfree);
    }
  }

  virtual ~strstreambuf() _NOEXCEPT;

  void freeze(bool _Freezeit = true);

  char *str()
  {       // freeze and return pointer to character array
    freeze();
    return gptr();
  }

  streamsize pcount() const
  {       // return size of writable character array
    return pptr() == 0 ? 0 : (streamsize)(pptr() - pbase());
  }

  strstreambuf(signed char *_Getptr,
               streamsize _Count,
               signed char *_Putptr = 0)
  {       // construct with [_Getptr, _Getptr + _Count), possibly mutable
    _Init(_Count, (char *)_Getptr, (char *)_Putptr);
  }

  strstreambuf(const signed char *_Getptr,
               streamsize _Count)
  {       // construct with [_Getptr, _Getptr + _Count), nonmutable
    _Init(_Count, (char *)_Getptr, 0, _Constant);
  }

  void clear()
  {       // free any allocated storage
    _Tidy();
  }

protected:
  virtual int overflow(int _Meta = EOF);
  virtual int pbackfail(int _Meta = EOF);
  virtual int underflow();
  virtual streampos seekoff(streamoff _Off_arg,
                            ios_base::seekdir _Way,
                      ios_base::openmode _Which = ios_base::in | ios_base::out);
  virtual streampos seekpos(streampos _Sp,
                      ios_base::openmode _Which = ios_base::in | ios_base::out);
  void _Init(streamsize _Count = 0, char *_Gp = 0, char *_Pp = 0,
             _Strstate _Mode = (_Strstate)0);
  void _Tidy();

private:
  enum
  {       // constant for default minimum buffer size
    _MINSIZE = 32};

  int _Minsize;           // the minimum buffer size
  char *_Pendsave;        // the saved end pointer during freeze
  char *_Seekhigh;        // the high-water pointer in character array
  _Strstate _Strmode;     // the stream state
  void *(*_Palloc)(size_t);       // the pointer to allocator function
  void (*_Pfree)(void *); // the pointer to free function
};

// strstreambuf OPERATORS
inline void swap(strstreambuf& _Left, strstreambuf& _Right)
{       // swap _Left and _Right strstreambufs
  _Left.swap(_Right);
}

// CLASS istrstream
class istrstream
  : public istream
{       // input stream associated with a character array
public:
  typedef istrstream _Myt;
  typedef istream _Mybase;
  typedef strstreambuf _Mysb;

  explicit istrstream(const char *_Ptr)
    : _Mybase(&_Strbuffer), _Strbuffer(_Ptr, 0)
  {       // construct with NTBS
  }

  istrstream(const char *_Ptr,
             streamsize _Count)
    : _Mybase(&_Strbuffer), _Strbuffer(_Ptr, _Count)
  {       // construct with [_Ptr, _Ptr + _Count)
  }

  explicit istrstream(char *_Ptr)
    : _Mybase(&_Strbuffer), _Strbuffer((const char *)_Ptr, 0)
  {       // construct with NTBS
  }

  istrstream(char *_Ptr,
             int _Count)
    : _Mybase(&_Strbuffer), _Strbuffer((const char *)_Ptr, _Count)
  {       // construct with [_Ptr, _Ptr + _Count)
  }

  istrstream(_Myt&& _Right)
    : _Mybase(&_Strbuffer)
  {       // construct by moving _Right
    _Assign_rv(std::forward<_Myt>(_Right));
  }

  _Myt& operator=(_Myt&& _Right)
  {       // move from _Right
    _Assign_rv(std::forward<_Myt>(_Right));
    return *this;
  }

  void _Assign_rv(_Myt&& _Right)
  {       // move from _Right
    if (this != &_Right)
    {       // different, swap base and buffer
      _Strbuffer.clear();
      this->swap(_Right);
    }
  }

  void swap(_Myt& _Right)
  {       // swap with _Right
    if (this != &_Right)
    {       // different, swap base and buffer
      _Mybase::swap(_Right);
      _Strbuffer.swap(_Right._Strbuffer);
    }
  }

  virtual ~istrstream() _NOEXCEPT;

  _Mysb *rdbuf() const
  {       // return pointer to character array buffer
    return (_Mysb *)&_Strbuffer;
  }

  char *str()
  {       // freeze and return pointer to character array
    return _Strbuffer.str();
  }

private:
  _Mysb _Strbuffer;       // the string buffer
};

// istrstream OPERATORS
inline void swap(istrstream& _Left, istrstream& _Right)
{       // swap _Left and _Right istrstreams
  _Left.swap(_Right);
}

// CLASS ostrstream
class ostrstream
  : public ostream
{       // output stream associated with a character array
public:
  typedef ostrstream _Myt;
  typedef ostream _Mybase;
  typedef strstreambuf _Mysb;

  ostrstream()
    : ostream(&_Strbuffer), _Strbuffer()
  {       // construct with empty character array
  }

  ostrstream(char *_Ptr,
             streamsize _Count,
             ios_base::openmode _Mode = ios_base::out);

  ostrstream(_Myt&& _Right)
    : _Mybase(&_Strbuffer)
  {       // construct by moving _Right
    _Assign_rv(std::forward<_Myt>(_Right));
  }

  _Myt& operator=(_Myt&& _Right)
  {       // move from _Right
    _Assign_rv(std::forward<_Myt>(_Right));
    return *this;
  }

  void _Assign_rv(_Myt&& _Right)
  {       // move from _Right
    if (this != &_Right)
    {       // different, swap base and buffer
      _Strbuffer.clear();
      this->swap(_Right);
    }
  }

  void swap(_Myt& _Right)
  {       // swap with _Right
    if (this != &_Right)
    {       // different, swap base and buffer
      _Mybase::swap(_Right);
      _Strbuffer.swap(_Right._Strbuffer);
    }
  }

  virtual ~ostrstream() _NOEXCEPT;

  _Mysb *rdbuf() const
  {       // return pointer to character array buffer
    return (_Mysb *)&_Strbuffer;
  }

  void freeze(bool _Freezeit = true)
  {       // freeze or unfreeze writing
    _Strbuffer.freeze(_Freezeit);
  }

  char *str()
  {       // freeze and return pointer to character array
    return _Strbuffer.str();
  }

  streamsize pcount() const
  {       // return size of writable character array
    return _Strbuffer.pcount();
  }

private:
  _Mysb _Strbuffer;       // the string buffer
};

// ostrstream OPERATORS
inline void swap(ostrstream& _Left, ostrstream& _Right)
{       // swap _Left and _Right ostrstreams
  _Left.swap(_Right);
}

// CLASS strstream
class strstream
  : public iostream
{       // input/output stream associated with character array buffer
public:
  typedef strstream _Myt;
  typedef iostream _Mybase;
  typedef strstreambuf _Mysb;

  typedef char char_type;
  typedef int int_type;
  typedef streampos pos_type;
  typedef streamoff off_type;

  strstream()
    : _Mybase(&_Strbuffer), _Strbuffer()
  {       // construct with empty character array
  }

  strstream(char *_Ptr, streamsize _Count,
            ios_base::openmode _Mode = ios_base::in | ios_base::out);

  strstream(_Myt&& _Right)
    : _Mybase(&_Strbuffer)
  {       // construct by moving _Right
    _Assign_rv(std::forward<_Myt>(_Right));
  }

  _Myt& operator=(_Myt&& _Right)
  {       // move from _Right
    _Assign_rv(std::forward<_Myt>(_Right));
    return *this;
  }

  void _Assign_rv(_Myt&& _Right)
  {       // move from _Right
    if (this != &_Right)
    {       // different, swap base and buffer
      _Strbuffer.clear();
      this->swap(_Right);
    }
  }

  void swap(_Myt& _Right)
  {       // swap with _Right
    if (this != &_Right)
    {       // different, swap base and buffer
      _Mybase::swap(_Right);
      _Strbuffer.swap(_Right._Strbuffer);
    }
  }

  virtual ~strstream() _NOEXCEPT;

  _Mysb *rdbuf() const
  {       // return pointer to character array buffer
    return (_Mysb *)&_Strbuffer;
  }

  void freeze(bool _Freezeit = true)
  {       // freeze or unfreeze writing
    _Strbuffer.freeze(_Freezeit);
  }

  char *str()
  {       // freeze and return pointer to character array
    return _Strbuffer.str();
  }

  streamsize pcount() const
  {       // return size of writable character array
    return _Strbuffer.pcount();
  }

private:
  _Mysb _Strbuffer;       // the string buffer
};

// strstream OPERATORS
inline void swap(strstream& _Left, strstream& _Right)
{       // swap _Left and _Right strstreams
  _Left.swap(_Right);
}

} /* namespace std */

#endif /* _STRSTREAM_ */

/*
 * Copyright (c) by P.J. Plauger. All rights reserved.
 * Consult your license regarding permissions and restrictions.
V6.50:0576 */
