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

#ifndef _SYSTEM_BUILD
#pragma system_include
#endif

#include <ios>

/* Module consistency. */
#pragma rtmodel="__dlib_full_locale_support", \
  _STRINGIFY(_DLIB_FULL_LOCALE_SUPPORT)

namespace std {

// I/O EXCEPTION MACROS

#if _HAS_EXCEPTIONS
  #define _TRY_IO_BEGIN  _TRY_BEGIN      /* begin try block */

  #define _CATCH_IO_END  _CATCH_ALL      /* catch block for _Myios */         \
    _Myios::setstate(ios_base::badbit, true);    /* set badbit and rethrow */ \
    _CATCH_END

  #define _CATCH_IO_(x)  _CATCH_ALL      /* catch block for basic_ios x */    \
    (x).setstate(ios_base::badbit, true);   /* set badbit and rethrow */      \
    _CATCH_END

#else /* _HAS_EXCEPTIONS */
  #define _TRY_IO_BEGIN  {       /* begin try block */
  #define _CATCH_IO_END  }       /* catch block for _Myios */
  #define _CATCH_IO_(x)  }       /* catch block for basic_ios x */
#endif /* _HAS_EXCEPTIONS */

#if _DLIB_FULL_LOCALE_SUPPORT
  #define _IOS_BASE_GETLOC ios_base::getloc()
  #define _OSTR_GETLOC     _Ostr.getloc()
#else
  #define _IOS_BASE_GETLOC
  #define _OSTR_GETLOC
#endif

// TEMPLATE CLASS basic_ostream
template<class _Elem,
         class _Traits>
class basic_ostream
  : virtual public basic_ios<_Elem, _Traits>
{       // control insertions into a stream buffer
public:
  typedef basic_ostream<_Elem, _Traits> _Myt;
  typedef basic_ios<_Elem, _Traits> _Myios;
  typedef basic_streambuf<_Elem, _Traits> _Mysb;
  typedef ostreambuf_iterator<_Elem, _Traits> _Iter;
  typedef num_put<_Elem, _Iter> _Nput;

  explicit basic_ostream(
    basic_streambuf<_Elem, _Traits> *_Strbuf,
    bool _Isstd = false)
  {       // construct from a stream buffer pointer
    _Myios::init(_Strbuf, _Isstd);
  }

  basic_ostream(_Uninitialized, bool _Addit = true)
  {       // construct uninitialized
    if (_Addit)
      this->_Addstd(this);    // suppress for basic_iostream
  }

protected:
  basic_ostream(_Myt&& _Right)
  {       // construct by moving _Right
    _Myios::init();
    _Myios::move(std::move(_Right));
  }

  _Myt& operator=(_Myt&& _Right)
  {       // move from _Right
    this->swap(_Right);
    return *this;
  }

  void swap(_Myt& _Right)
  {       // swap with _Right
    if (this != &_Right)
      _Myios::swap(_Right);
  }

public:
  basic_ostream(const _Myt&) = delete;
  _Myt& operator=(const _Myt&) = delete;

  virtual ~basic_ostream() _NOEXCEPT
  {       // destroy the object
  }

  typedef typename _Traits::int_type int_type;
  typedef typename _Traits::pos_type pos_type;
  typedef typename _Traits::off_type off_type;

  class _Sentry_base
  {       // stores thread lock and reference to output stream
  public:
    _Sentry_base(_Myt& _Ostr)
      : _Myostr(_Ostr)
    {       // lock the stream buffer, if there
      if (_Myostr.rdbuf() != 0)
        _Myostr.rdbuf()->_Lock();
    }

    ~_Sentry_base() _NOEXCEPT
    {       // destroy after unlocking
      if (_Myostr.rdbuf() != 0)
        _Myostr.rdbuf()->_Unlock();
    }

    _Myt& _Myostr;  // the output stream, for _Unlock call at destruction

  private:
    _Sentry_base& operator=(const _Sentry_base&);
  };

  // Sentry object to be used in flush. Does everything a normal sentry object
  // does, except it does not call flush on any tied stream. This way
  // stack usage analysis does not have to deal with the apparent recursion.
  class _Flush_sentry
    : public _Sentry_base
  {
  public:
    _Flush_sentry(_Myt& _Ostr)
      : _Sentry_base(_Ostr)
    {       // construct locking and testing stream
      _Ok = _Ostr.good();     // store test only after flushing tie
    }

    ~_Flush_sentry() _NOEXCEPT
    {       // destroy the object
      #if _HAS_EXCEPTIONS
      if (!::std::uncaught_exception())
          this->_Myostr._Osfx();
      #else
        this->_Myostr._Osfx();
      #endif
    }

    explicit operator bool() const
    {       // test if stream state okay
      return _Ok;
    }

  private:
    bool _Ok;       // true if stream state okay at construction
  };

  class sentry
    : public _Flush_sentry
  {       // stores thread lock and state of stream
  public:
    explicit sentry(_Myt& _Ostr)
      : _Flush_sentry(_Ostr)
    {       // construct locking and testing stream
      if (_Ostr.good() && _Ostr.tie() != 0 && _Ostr.tie() != &_Ostr)
        _Ostr.tie()->flush();
    }

    sentry(const sentry&) = delete;
    sentry& operator=(const sentry&) = delete;
  };

  bool opfx()
  {       // test stream state and flush tie stream as needed (retained)
    if (this->good() && _Myios::tie() != 0 && _Myios::tie() != this)
      _Myios::tie()->flush();
    return this->good();
  }

  void osfx()
  {       // perform any wrapup (retained)
    _Osfx();
  }

  void _Osfx()
  {       // perform any wrapup
    _TRY_BEGIN
      if (this->good() && this->flags() & ios_base::unitbuf)
        if (_Myios::rdbuf()->pubsync() == -1)   // flush stream as needed
          _Myios::setstate(ios_base::badbit);
    _CATCH_ALL
    _CATCH_END
  }

  _Myt& operator<<(_Myt& (*_Pfn)(_Myt&))
  {       // call basic_ostream manipulator
    _DEBUG_POINTER(_Pfn);
    return (*_Pfn)(*this);
  }

  _Myt& operator<<(_Myios& (*_Pfn)(_Myios&))
  {       // call basic_ios manipulator
    _DEBUG_POINTER(_Pfn);
    (*_Pfn)(*(_Myios *)this);
    return *this;
  }

  _Myt& operator<<(ios_base& (*_Pfn)(ios_base&))
  {       // call ios_base manipulator
    _DEBUG_POINTER(_Pfn);
    (*_Pfn)(*(ios_base *)this);
    return *this;
  }

  _NOINLINE _Myt& operator<<(bool _Val)
  {       // insert a boolean
    ios_base::iostate _State = ios_base::goodbit;
    const sentry _Ok(*this);

    if (_Ok)
    {       // state okay, use facet to insert
      const _Nput& _Nput_fac = use_facet< _Nput >(_IOS_BASE_GETLOC);

      _TRY_IO_BEGIN
      if (_Nput_fac.put(_Iter(_Myios::rdbuf()), *this,
                        _Myios::fill(), _Val).failed())
        _State |= ios_base::badbit;
      _CATCH_IO_END
    }

    _Myios::setstate(_State);
    return *this;
  }

  _NOINLINE _Myt& operator<<(short _Val)
  {       // insert a short
    ios_base::iostate _State = ios_base::goodbit;
    const sentry _Ok(*this);

    if (_Ok)
    {       // state okay, use facet to insert
      const _Nput& _Nput_fac = use_facet< _Nput >(_IOS_BASE_GETLOC);
      ios_base::fmtflags _Bfl = this->flags() & ios_base::basefield;
      long _Tmp =   (_Bfl == ios_base::oct || _Bfl == ios_base::hex)
                  ? (long)(unsigned short)_Val
                  : (long)_Val;

      _TRY_IO_BEGIN
      if (_Nput_fac.put(_Iter(_Myios::rdbuf()), *this,
                        _Myios::fill(), _Tmp).failed())
        _State |= ios_base::badbit;
      _CATCH_IO_END
    }

    _Myios::setstate(_State);
    return *this;
  }

  _NOINLINE _Myt& operator<<(unsigned short _Val)
  {       // insert an unsigned short
    ios_base::iostate _State = ios_base::goodbit;
    const sentry _Ok(*this);

    if (_Ok)
    {       // state okay, use facet to insert
      const _Nput& _Nput_fac = use_facet< _Nput >(_IOS_BASE_GETLOC);

      _TRY_IO_BEGIN
      if (_Nput_fac.put(_Iter(_Myios::rdbuf()), *this,
                        _Myios::fill(), (unsigned long)_Val).failed())
        _State |= ios_base::badbit;
      _CATCH_IO_END
    }

    _Myios::setstate(_State);
    return *this;
  }

  _NOINLINE _Myt& operator<<(int _Val)
  {       // insert an int
    ios_base::iostate _State = ios_base::goodbit;
    const sentry _Ok(*this);

    if (_Ok)
    {       // state okay, use facet to insert
      const _Nput& _Nput_fac = use_facet< _Nput >(_IOS_BASE_GETLOC);
      ios_base::fmtflags _Bfl =  this->flags() & ios_base::basefield;
      long _Tmp =   (_Bfl == ios_base::oct || _Bfl == ios_base::hex)
                  ? (long)(unsigned int)_Val
                  : (long)_Val;

      _TRY_IO_BEGIN
      if (_Nput_fac.put(_Iter(_Myios::rdbuf()), *this,
                        _Myios::fill(), _Tmp).failed())
        _State |= ios_base::badbit;
      _CATCH_IO_END
    }

    _Myios::setstate(_State);
    return *this;
  }

  _NOINLINE _Myt& operator<<(unsigned int _Val)
  {       // insert an unsigned int
    ios_base::iostate _State = ios_base::goodbit;
    const sentry _Ok(*this);

    if (_Ok)
    {       // state okay, use facet to insert
      const _Nput& _Nput_fac = use_facet< _Nput >(_IOS_BASE_GETLOC);

      _TRY_IO_BEGIN
      if (_Nput_fac.put(_Iter(_Myios::rdbuf()), *this,
                        _Myios::fill(), (unsigned long)_Val).failed())
        _State |= ios_base::badbit;
      _CATCH_IO_END
    }

    _Myios::setstate(_State);
    return *this;
  }

  _NOINLINE _Myt& operator<<(long _Val)
  {       // insert a long
    ios_base::iostate _State = ios_base::goodbit;
    const sentry _Ok(*this);

    if (_Ok)
    {       // state okay, use facet to insert
      const _Nput& _Nput_fac = use_facet< _Nput >(_IOS_BASE_GETLOC);

      _TRY_IO_BEGIN
      if (_Nput_fac.put(_Iter(_Myios::rdbuf()), *this,
                        _Myios::fill(), _Val).failed())
        _State |= ios_base::badbit;
      _CATCH_IO_END
    }

    _Myios::setstate(_State);
    return *this;
  }

  _NOINLINE _Myt& operator<<(unsigned long _Val)
  {       // insert an unsigned long
    ios_base::iostate _State = ios_base::goodbit;
    const sentry _Ok(*this);

    if (_Ok)
    {       // state okay, use facet to insert
      const _Nput& _Nput_fac = use_facet< _Nput >(_IOS_BASE_GETLOC);

      _TRY_IO_BEGIN
      if (_Nput_fac.put(_Iter(_Myios::rdbuf()), *this,
                        _Myios::fill(), _Val).failed())
        _State |= ios_base::badbit;
      _CATCH_IO_END
    }

    _Myios::setstate(_State);
    return *this;
  }

  _NOINLINE _Myt& operator<<(long long _Val)
  {       // insert a long long
    ios_base::iostate _State = ios_base::goodbit;
    const sentry _Ok(*this);

    if (_Ok)
    {       // state okay, use facet to insert
      const _Nput& _Nput_fac = use_facet< _Nput >(_IOS_BASE_GETLOC);

      _TRY_IO_BEGIN
      if (_Nput_fac.put(_Iter(_Myios::rdbuf()), *this,
                        _Myios::fill(), _Val).failed())
        _State |= ios_base::badbit;
      _CATCH_IO_END
    }

    _Myios::setstate(_State);
    return *this;
  }

  _NOINLINE _Myt& operator<<(unsigned long long _Val)
  {       // insert an unsigned long long
    ios_base::iostate _State = ios_base::goodbit;
    const sentry _Ok(*this);

    if (_Ok)
    {       // state okay, use facet to insert
      const _Nput& _Nput_fac = use_facet< _Nput >(_IOS_BASE_GETLOC);

      _TRY_IO_BEGIN
      if (_Nput_fac.put(_Iter(_Myios::rdbuf()), *this,
                        _Myios::fill(), _Val).failed())
        _State |= ios_base::badbit;
      _CATCH_IO_END
    }

    _Myios::setstate(_State);
    return *this;
  }

  _NOINLINE _Myt& operator<<(float _Val)
  {       // insert a float
    ios_base::iostate _State = ios_base::goodbit;
    const sentry _Ok(*this);

    if (_Ok)
    {       // state okay, use facet to insert
      const _Nput& _Nput_fac = use_facet< _Nput >(_IOS_BASE_GETLOC);

      _TRY_IO_BEGIN
      if (_Nput_fac.put(_Iter(_Myios::rdbuf()), *this,
                        _Myios::fill(), (double)_Val).failed())
        _State |= ios_base::badbit;
      _CATCH_IO_END
    }

    _Myios::setstate(_State);
    return *this;
  }

  _NOINLINE _Myt& operator<<(double _Val)
  {       // insert a double
    ios_base::iostate _State = ios_base::goodbit;
    const sentry _Ok(*this);

    if (_Ok)
    {       // state okay, use facet to insert
      const _Nput& _Nput_fac = use_facet< _Nput >(_IOS_BASE_GETLOC);

      _TRY_IO_BEGIN
      if (_Nput_fac.put(_Iter(_Myios::rdbuf()), *this,
                        _Myios::fill(), _Val).failed())
        _State |= ios_base::badbit;
      _CATCH_IO_END
    }

    _Myios::setstate(_State);
    return *this;
  }

  _NOINLINE _Myt& operator<<(long double _Val)
  {       // insert a long double
    ios_base::iostate _State = ios_base::goodbit;
    const sentry _Ok(*this);

    if (_Ok)
    {       // state okay, use facet to insert
      const _Nput& _Nput_fac = use_facet< _Nput >(_IOS_BASE_GETLOC);

      _TRY_IO_BEGIN
      if (_Nput_fac.put(_Iter(_Myios::rdbuf()), *this,
                        _Myios::fill(), _Val).failed())
        _State |= ios_base::badbit;
      _CATCH_IO_END
    }

    _Myios::setstate(_State);
    return *this;
  }

  _NOINLINE _Myt& operator<<(const void *_Val)
  {       // insert a void pointer
    ios_base::iostate _State = ios_base::goodbit;
    const sentry _Ok(*this);

    if (_Ok)
    {       // state okay, use facet to insert
      const _Nput& _Nput_fac = use_facet< _Nput >(_IOS_BASE_GETLOC);

      _TRY_IO_BEGIN
      if (_Nput_fac.put(_Iter(_Myios::rdbuf()), *this,
                        _Myios::fill(), _Val).failed())
        _State |= ios_base::badbit;
      _CATCH_IO_END
    }

    _Myios::setstate(_State);
    return *this;
  }

  _NOINLINE _Myt& operator<<(_Mysb *_Strbuf)
  {       // insert until end-of-file from a stream buffer
    ios_base::iostate _State = ios_base::goodbit;
    bool _Copied = false;
    const sentry _Ok(*this);

    if (_Ok && _Strbuf != 0)
      for (int_type _Meta = _Traits::eof(); ; _Copied = true)
      {       // extract another character from stream buffer
        _TRY_BEGIN
          _Meta =   _Traits::eq_int_type(_Traits::eof(), _Meta)
                  ? _Strbuf->sgetc()
                  : _Strbuf->snextc();
        _CATCH_ALL
          _Myios::setstate(ios_base::failbit);
          _RERAISE;
        _CATCH_END

        if (_Traits::eq_int_type(_Traits::eof(), _Meta))
          break;  // end of file, quit

        _TRY_IO_BEGIN
        if (_Traits::eq_int_type(_Traits::eof(),
                                 _Myios::rdbuf()->sputc(
                                   _Traits::to_char_type(_Meta))))
        {       // insertion failed, quit
          _State |= ios_base::badbit;
          break;
        }
        _CATCH_IO_END
      }

    this->width(0);
    _Myios::setstate(  _Strbuf == 0
                     ? ios_base::badbit
                     : !_Copied ? _State | ios_base::failbit : _State);
    return *this;
  }

  _NOINLINE _Myt& put(_Elem _Ch)
  {       // insert a character
    ios_base::iostate _State = ios_base::goodbit;
    const sentry _Ok(*this);

    if (!_Ok)
      _State |= ios_base::badbit;
    else
    {       // state okay, insert character
      _TRY_IO_BEGIN
      if (_Traits::eq_int_type(_Traits::eof(),
                               _Myios::rdbuf()->sputc(_Ch)))
        _State |= ios_base::badbit;
      _CATCH_IO_END
    }

    _Myios::setstate(_State);
    return *this;
  }

  _NOINLINE _Myt& write(const _Elem *_Str,
              streamsize _Count)
  {       // insert _Count characters from array _Str
    ios_base::iostate _State = ios_base::goodbit;
    const sentry _Ok(*this);

    if (!_Ok)
      _State |= ios_base::badbit;
    else if (0 < _Count)
    {       // state okay, insert characters
      _DEBUG_POINTER(_Str);
      _TRY_IO_BEGIN
      if (_Myios::rdbuf()->sputn(_Str, _Count) != _Count)
        _State |= ios_base::badbit;
      _CATCH_IO_END
    }

    _Myios::setstate(_State);
    return *this;
  }

  _NOINLINE _Myt& flush()
  {       // flush output stream
    if (_Myios::rdbuf() != 0)
    {       // buffer exists, flush it
      const _Flush_sentry _Ok(*this);

      if (_Ok && _Myios::rdbuf()->pubsync() == -1)
        _Myios::setstate(ios_base::badbit);     // sync failed
    }
    return *this;
  }

  _NOINLINE _Myt& seekp(pos_type _Pos)
  {       // set output stream position to _Pos
    const sentry _Ok(*this);

    if (   !this->fail()
        && (off_type)_Myios::rdbuf()->pubseekpos(_Pos,
                                                 ios_base::out) == _BADOFF)
      _Myios::setstate(ios_base::failbit);
    return *this;
  }

  _NOINLINE _Myt& seekp(off_type _Off, ios_base::seekdir _Way)
  {       // change output stream position by _Off, according to _Way
    const sentry _Ok(*this);

    if (   !this->fail()
        && (off_type)_Myios::rdbuf()->pubseekoff(_Off, _Way,
                                                 ios_base::out) == _BADOFF)
      _Myios::setstate(ios_base::failbit);
    return *this;
  }

  _NOINLINE pos_type tellp()
  {       // return output stream position
    const sentry _Ok(*this);

    if (!this->fail())
      return _Myios::rdbuf()->pubseekoff(0, ios_base::cur, ios_base::out);
    else
      return pos_type(_BADOFF);
  }
};

// basic_ostream TEMPLATE OPERATORS

// INSERTERS
template<class _Elem,
         class _Traits> inline
basic_ostream<_Elem, _Traits>& operator<<(
basic_ostream<_Elem, _Traits>& _Ostr, const char *_Val)
{       // insert NTBS
  ios_base::iostate _State = ios_base::goodbit;
  streamsize _Count = (streamsize)::strlen(_Val);     // may overflow
  streamsize _Pad =   _Ostr.width() <= 0 || _Ostr.width() <= _Count
                   ? 0
                   : _Ostr.width() - _Count;
  const typename basic_ostream<_Elem, _Traits>::sentry _Ok(_Ostr);

  if (!_Ok)
    _State |= ios_base::badbit;
  else
  {       // state okay, insert characters
    _TRY_IO_BEGIN
    const ctype<_Elem>& _Ctype_fac = use_facet< ctype<_Elem> >(_OSTR_GETLOC);
    if ((_Ostr.flags() & ios_base::adjustfield) != ios_base::left)
      for (; 0 < _Pad; --_Pad)        // pad on left
        if (_Traits::eq_int_type(_Traits::eof(),
                                 _Ostr.rdbuf()->sputc(_Ostr.fill())))
        {       // insertion failed, quit
          _State |= ios_base::badbit;
          break;
        }

    for (; _State == ios_base::goodbit && 0 < _Count; --_Count, ++_Val)
      if (_Traits::eq_int_type(_Traits::eof(),
                               _Ostr.rdbuf()->sputc(_Ctype_fac.widen(*_Val))))
        _State |= ios_base::badbit;

    if (_State == ios_base::goodbit)
      for (; 0 < _Pad; --_Pad)        // pad on right
        if (_Traits::eq_int_type(_Traits::eof(),
                                 _Ostr.rdbuf()->sputc(_Ostr.fill())))
        {       // insertion failed, quit
          _State |= ios_base::badbit;
          break;
        }
    _Ostr.width(0);
    _CATCH_IO_(_Ostr)
  }

  _Ostr.setstate(_State);
  return _Ostr;
}

template<class _Elem,
         class _Traits> inline
basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Ostr,
                                          char _Ch)
{       // insert a character
  ios_base::iostate _State = ios_base::goodbit;
  const typename basic_ostream<_Elem, _Traits>::sentry _Ok(_Ostr);

  if (_Ok)
  {       // state okay, insert
    const ctype<_Elem>& _Ctype_fac = use_facet< ctype<_Elem> >(_OSTR_GETLOC);
    streamsize _Pad = _Ostr.width() <= 1 ? 0 : _Ostr.width() - 1;

    _TRY_IO_BEGIN
    if ((_Ostr.flags() & ios_base::adjustfield) != ios_base::left)
      for (; _State == ios_base::goodbit && 0 < _Pad;
           --_Pad) // pad on left
        if (_Traits::eq_int_type(_Traits::eof(),
                                 _Ostr.rdbuf()->sputc(_Ostr.fill())))
          _State |= ios_base::badbit;

    if (   _State == ios_base::goodbit
        && _Traits::eq_int_type(_Traits::eof(),
                                _Ostr.rdbuf()->sputc(_Ctype_fac.widen(_Ch))))
      _State |= ios_base::badbit;

    for (; _State == ios_base::goodbit && 0 < _Pad; --_Pad) // pad on right
      if (_Traits::eq_int_type(_Traits::eof(),
                               _Ostr.rdbuf()->sputc(_Ostr.fill())))
        _State |= ios_base::badbit;
    _CATCH_IO_(_Ostr)
  }

  _Ostr.width(0);
  _Ostr.setstate(_State);
  return _Ostr;
}

template<class _Traits> inline
basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>& _Ostr,
                                         const char *_Val)
{       // insert NTBS into char stream
  typedef char _Elem;
  typedef basic_ostream<_Elem, _Traits> _Myos;
  ios_base::iostate _State = ios_base::goodbit;
  streamsize _Count = (streamsize)_Traits::length(_Val);  // may overflow
  streamsize _Pad =   _Ostr.width() <= 0 || _Ostr.width() <= _Count
                    ? 0
                    : _Ostr.width() - _Count;
  const typename _Myos::sentry _Ok(_Ostr);

  if (!_Ok)
    _State |= ios_base::badbit;
  else
  {       // state okay, insert
    _TRY_IO_BEGIN
    if ((_Ostr.flags() & ios_base::adjustfield) != ios_base::left)
      for (; 0 < _Pad; --_Pad)        // pad on left
        if (_Traits::eq_int_type(_Traits::eof(),
                                 _Ostr.rdbuf()->sputc(_Ostr.fill())))
        {       // insertion failed, quit
          _State |= ios_base::badbit;
          break;
        }

    if (   _State == ios_base::goodbit
        && _Ostr.rdbuf()->sputn(_Val, _Count) != _Count)
      _State |= ios_base::badbit;

    if (_State == ios_base::goodbit)
      for (; 0 < _Pad; --_Pad)        // pad on right
        if (_Traits::eq_int_type(_Traits::eof(),
                                 _Ostr.rdbuf()->sputc(_Ostr.fill())))
        {       // insertion failed, quit
          _State |= ios_base::badbit;
          break;
        }
    _Ostr.width(0);
    _CATCH_IO_(_Ostr)
  }

  _Ostr.setstate(_State);
  return _Ostr;
}

template<class _Traits> inline
basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>& _Ostr,
                                         char _Ch)
{       // insert a char into char stream
  typedef char _Elem;
  typedef basic_ostream<_Elem, _Traits> _Myos;
  ios_base::iostate _State = ios_base::goodbit;
  const typename _Myos::sentry _Ok(_Ostr);

  if (_Ok)
  {       // state okay, insert
    streamsize _Pad = _Ostr.width() <= 1 ? 0 : _Ostr.width() - 1;

    _TRY_IO_BEGIN
    if ((_Ostr.flags() & ios_base::adjustfield) != ios_base::left)
      for (; _State == ios_base::goodbit && 0 < _Pad; --_Pad) // pad on left
        if (_Traits::eq_int_type(_Traits::eof(),
                                 _Ostr.rdbuf()->sputc(_Ostr.fill())))
          _State |= ios_base::badbit;

    if (_State == ios_base::goodbit
        && _Traits::eq_int_type(_Traits::eof(),
                                _Ostr.rdbuf()->sputc(_Ch)))
      _State |= ios_base::badbit;

    for (; _State == ios_base::goodbit && 0 < _Pad; --_Pad) // pad on right
      if (_Traits::eq_int_type(_Traits::eof(),
                               _Ostr.rdbuf()->sputc(_Ostr.fill())))
        _State |= ios_base::badbit;
    _CATCH_IO_(_Ostr)
  }

  _Ostr.width(0);
  _Ostr.setstate(_State);
  return _Ostr;
}

template<class _Elem,
         class _Traits> inline
basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Ostr,
                                          const _Elem *_Val)
{       // insert NTCS
  typedef basic_ostream<_Elem, _Traits> _Myos;

  ios_base::iostate _State = ios_base::goodbit;
  streamsize _Count = (streamsize)_Traits::length(_Val);  // may overflow
  streamsize _Pad =   _Ostr.width() <= 0 || _Ostr.width() <= _Count
                    ? 0
                    : _Ostr.width() - _Count;
  const typename _Myos::sentry _Ok(_Ostr);

  if (!_Ok)
    _State |= ios_base::badbit;
  else
  {       // state okay, insert
    _TRY_IO_BEGIN
    if ((_Ostr.flags() & ios_base::adjustfield) != ios_base::left)
      for (; 0 < _Pad; --_Pad)        // pad on left
        if (_Traits::eq_int_type(_Traits::eof(),
                                 _Ostr.rdbuf()->sputc(_Ostr.fill())))
        {       // insertion failed, quit
          _State |= ios_base::badbit;
          break;
        }

    if (   _State == ios_base::goodbit
        && _Ostr.rdbuf()->sputn(_Val, _Count) != _Count)
      _State |= ios_base::badbit;

    if (_State == ios_base::goodbit)
      for (; 0 < _Pad; --_Pad)        // pad on right
        if (_Traits::eq_int_type(_Traits::eof(),
                                 _Ostr.rdbuf()->sputc(_Ostr.fill())))
        {       // insertion failed, quit
          _State |= ios_base::badbit;
          break;
        }
    _Ostr.width(0);
    _CATCH_IO_(_Ostr)
  }

  _Ostr.setstate(_State);
  return _Ostr;
}

template<class _Elem,
         class _Traits> inline
basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Ostr,
                                          _Elem _Ch)
{       // insert a character
  typedef basic_ostream<_Elem, _Traits> _Myos;

  ios_base::iostate _State = ios_base::goodbit;
  const typename _Myos::sentry _Ok(_Ostr);

  if (_Ok)
  {       // state okay, insert
    streamsize _Pad = _Ostr.width() <= 1 ? 0 : _Ostr.width() - 1;

    _TRY_IO_BEGIN
    if ((_Ostr.flags() & ios_base::adjustfield) != ios_base::left)
      for (; _State == ios_base::goodbit && 0 < _Pad; --_Pad) // pad on left
        if (_Traits::eq_int_type(_Traits::eof(),
                                 _Ostr.rdbuf()->sputc(_Ostr.fill())))
          _State |= ios_base::badbit;

    if (   _State == ios_base::goodbit
        && _Traits::eq_int_type(_Traits::eof(), _Ostr.rdbuf()->sputc(_Ch)))
      _State |= ios_base::badbit;

    for (; _State == ios_base::goodbit && 0 < _Pad; --_Pad) // pad on right
      if (_Traits::eq_int_type(_Traits::eof(),
                               _Ostr.rdbuf()->sputc(_Ostr.fill())))
        _State |= ios_base::badbit;
    _CATCH_IO_(_Ostr)
  }

  _Ostr.width(0);
  _Ostr.setstate(_State);
  return _Ostr;
}

template<class _Traits> inline
basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>& _Ostr,
                                         const signed char *_Val)
{       // insert a signed char NTBS
  return _Ostr << (const char *)_Val;
}

template<class _Traits> inline
basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>& _Ostr,
                                         signed char _Ch)
{       // insert a signed char
  return _Ostr << (char)_Ch;
}

template<class _Traits> inline
basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>& _Ostr,
                                         const unsigned char *_Val)
{       // insert an unsigned char NTBS
  return _Ostr << (const char *)_Val;
}

template<class _Traits> inline
basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>& _Ostr,
                                         unsigned char _Ch)
{       // insert an unsigned char
  return _Ostr << (char)_Ch;
}

template<class _Elem,
         class _Traits,
         class _Ty> inline
basic_ostream<_Elem, _Traits>&
operator<<(basic_ostream<_Elem, _Traits>&& _Ostr, const _Ty& _Val)
{       // insert to rvalue stream
  return _Ostr << _Val;
}

// MANIPULATORS
template<class _Elem,
         class _Traits> inline
basic_ostream<_Elem, _Traits>&
endl(basic_ostream<_Elem, _Traits>& _Ostr)
{       // insert newline and flush stream
  _Ostr.put(_Ostr.widen('\n'));
  _Ostr.flush();
  return _Ostr;
}

template<class _Elem,
         class _Traits> inline
basic_ostream<_Elem, _Traits>&
ends(basic_ostream<_Elem, _Traits>& _Ostr)
{       // insert null character
  _Ostr.put(_Elem());
  return _Ostr;
}

template<class _Elem,
         class _Traits> inline
basic_ostream<_Elem, _Traits>&
flush(basic_ostream<_Elem, _Traits>& _Ostr)
{       // flush stream
  _Ostr.flush();
  return _Ostr;
}

// INSERTER FOR error_category
template<class _Elem,
         class _Traits> inline
basic_ostream<_Elem, _Traits>&
operator<<(basic_ostream<_Elem, _Traits>& _Ostr,
           const error_code& _Errcode)
{       // display error code
  return _Ostr << _Errcode.category().name() << ':' << _Errcode.value();
}

#undef _IOS_BASE_GETLOC
#undef _OSTR_GETLOC

} /* namespace std */

#endif /* _OSTREAM_ */

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