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

#ifndef _SYSTEM_BUILD
#pragma system_include
#endif

#include <xlocnum>

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

namespace std {

#if _DLIB_FULL_LOCALE_SUPPORT
  #define _GETLOC getloc()
#else
  #define _GETLOC
#endif

// TEMPLATE CLASS basic_ios
template<class _Elem,
         class _Traits>
class basic_ios
  : public ios_base
{       // base class for basic_istream/basic_ostream
public:
  typedef basic_ios<_Elem, _Traits> _Myt;
  typedef basic_ostream<_Elem, _Traits> _Myos;
  typedef basic_streambuf<_Elem, _Traits> _Mysb;
  typedef ctype<_Elem> _Ctype;
  typedef _Elem char_type;
  typedef _Traits traits_type;
  typedef typename _Traits::int_type int_type;
  typedef typename _Traits::pos_type pos_type;
  typedef typename _Traits::off_type off_type;

  explicit basic_ios(_Mysb *_Strbuf)
  {       // construct from stream buffer pointer
    init(_Strbuf);
  }

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

  void clear(iostate _State = goodbit,
             bool _Reraise = false)
  {       // set state, possibly reraise exception
    ios_base::clear((iostate)(_Mystrbuf == 0
                              ? (int)_State | (int)badbit
                              : (int)_State), _Reraise);
  }

  void clear(io_state _State)
  {       // set state to _State
    clear((iostate)_State);
  }

  void setstate(iostate _State,
                bool _Reraise = false)
  {       // merge _State into state, possibly reraise exception
    if (_State != goodbit)
      clear((iostate)((int)rdstate() | (int)_State), _Reraise);
  }

  void setstate(io_state _State)
  {       // merge _State into state
    setstate((iostate)_State);
  }

  _Myt& copyfmt(const _Myt& _Right)
  {       // copy format parameters
    _Tiestr = _Right.tie();
    _Fillch = _Right.fill();
    ios_base::copyfmt(_Right);
    return *this;
  }

  _Myos *tie() const
  {       // return tie pointer
    return _Tiestr;
  }

  _Myos *tie(_Myos *_Newtie)
  {       // set tie pointer
    _Myos *_Oldtie = _Tiestr;
    _Tiestr = _Newtie;
    return _Oldtie;
  }

  _Mysb *rdbuf() const
  {       // return stream buffer pointer
    return _Mystrbuf;
  }

  _Mysb *rdbuf(_Mysb *_Strbuf)
  {       // set stream buffer pointer
    _Mysb *_Oldstrbuf = _Mystrbuf;
    _Mystrbuf = _Strbuf;
    clear();
    return _Oldstrbuf;
  }

  #if _DLIB_FULL_LOCALE_SUPPORT
    locale imbue(const locale& _Loc)
    {       // set locale to argument
      locale _Oldlocale = ios_base::imbue(_Loc);
      if (rdbuf() != 0)
        rdbuf()->pubimbue(_Loc);
      return _Oldlocale;
    }
  #endif

  _Elem fill() const
  {       // return fill character
    return _Fillch;
  }

  _Elem fill(_Elem _Newfill)
  {       // set fill character
    _Elem _Oldfill = _Fillch;
    _Fillch = _Newfill;
    return _Oldfill;
  }

  char narrow(_Elem _Ch, char _Dflt = '\0') const
  {       // convert _Ch to byte using imbued locale
    const _Ctype& _Ctype_fac = use_facet< _Ctype >(_GETLOC);
    return _Ctype_fac.narrow(_Ch, _Dflt);
  }

  _Elem widen(char _Byte) const
  {       // convert _Byte to character using imbued locale
    const _Ctype& _Ctype_fac = use_facet< _Ctype >(_GETLOC);
    return _Ctype_fac.widen(_Byte);
  }

  void move(_Myt& _Right)
  {       // assign by moving _Right
    if (this != &_Right)
    {       // different, do the move
      _Mystrbuf = 0;
      _Tiestr = 0;
      this->swap(_Right);
    }
  }

  void move(_Myt&& _Right)
  {       // assign by moving _Right
    if (this != &_Right)
    {       // different, do the move
      _Mystrbuf = 0;
      _Tiestr = 0;
      this->swap(_Right);
    }
  }

  void swap(_Myt& _Right) _NOEXCEPT
  {       // swap all but rdbuf() with right
    ios_base::swap(_Right);
    std::swap(_Fillch, _Right._Fillch);
    std::swap(_Tiestr, _Right._Tiestr);
  }

  void set_rdbuf(_Mysb *_Strbuf)
  {       // set stream buffer pointer without changing state
    _Mystrbuf = _Strbuf;
  }

protected:
  void init(_Mysb *_Strbuf = 0,
            bool _Isstd = false)
  {       // initialize with stream buffer pointer
    _Init();        // initialize ios_base
    _Mystrbuf = _Strbuf;
    _Tiestr = 0;
    _Fillch = widen(' ');

    if (_Mystrbuf == 0)
      setstate(badbit);

    if (_Isstd)
      _Addstd(this);  // special handling for standard streams
  }

  basic_ios()
  {       // default constructor, do nothing
  }

private:
  _Mysb *_Mystrbuf;       // pointer to stream buffer
  _Myos *_Tiestr; // pointer to tied output stream
  _Elem _Fillch;  // the fill character

public:
  basic_ios(const _Myt&) = delete;
  _Myt& operator=(const _Myt&) = delete;
};

// MANIPULATORS
inline ios_base& boolalpha(ios_base& _Iosbase)
{       // set boolalpha
  _Iosbase.setf(ios_base::boolalpha);
  return _Iosbase;
}

inline ios_base& dec(ios_base& _Iosbase)
{       // set basefield to dec
  _Iosbase.setf(ios_base::dec, ios_base::basefield);
  return _Iosbase;
}

inline ios_base& defaultfloat(ios_base& _Iosbase)
{       // clear floatfield
  _Iosbase.unsetf(ios_base::floatfield);
  return _Iosbase;
}

inline ios_base& fixed(ios_base& _Iosbase)
{       // set floatfield to fixed
  _Iosbase.setf(ios_base::fixed, ios_base::floatfield);
  return _Iosbase;
}

inline ios_base& hex(ios_base& _Iosbase)
{       // set basefield to hex
  _Iosbase.setf(ios_base::hex, ios_base::basefield);
  return _Iosbase;
}

inline ios_base& hexfloat(ios_base& _Iosbase)
{       // set floatfield to hexfloat
  _Iosbase.setf(ios_base::hexfloat, ios_base::floatfield);
  return _Iosbase;
}

inline ios_base& internal(ios_base& _Iosbase)
{       // set adjustfield to internal
  _Iosbase.setf(ios_base::internal, ios_base::adjustfield);
  return _Iosbase;
}

inline ios_base& left(ios_base& _Iosbase)
{       // set adjustfield to left
  _Iosbase.setf(ios_base::left, ios_base::adjustfield);
  return _Iosbase;
}

inline ios_base& noboolalpha(ios_base& _Iosbase)
{       // clear boolalpha
  _Iosbase.unsetf(ios_base::boolalpha);
  return _Iosbase;
}

inline ios_base& noshowbase(ios_base& _Iosbase)
{       // clear showbase
  _Iosbase.unsetf(ios_base::showbase);
  return _Iosbase;
}

inline ios_base& noshowpoint(ios_base& _Iosbase)
{       // clear showpoint
  _Iosbase.unsetf(ios_base::showpoint);
  return _Iosbase;
}

inline ios_base& noshowpos(ios_base& _Iosbase)
{       // clear showpos
  _Iosbase.unsetf(ios_base::showpos);
  return _Iosbase;
}

inline ios_base& noskipws(ios_base& _Iosbase)
{       // clear skipws
  _Iosbase.unsetf(ios_base::skipws);
  return _Iosbase;
}

inline ios_base& nounitbuf(ios_base& _Iosbase)
{       // clear unitbuf
  _Iosbase.unsetf(ios_base::unitbuf);
  return _Iosbase;
}

inline ios_base& nouppercase(ios_base& _Iosbase)
{       // clear uppercase
  _Iosbase.unsetf(ios_base::uppercase);
  return _Iosbase;
}

inline ios_base& oct(ios_base& _Iosbase)
{       // set oct in basefield
  _Iosbase.setf(ios_base::oct, ios_base::basefield);
  return _Iosbase;
}

inline ios_base& right(ios_base& _Iosbase)
{       // set right in adjustfield
  _Iosbase.setf(ios_base::right, ios_base::adjustfield);
  return _Iosbase;
}

inline ios_base& scientific(ios_base& _Iosbase)
{       // set scientific in floatfield
  _Iosbase.setf(ios_base::scientific, ios_base::floatfield);
  return _Iosbase;
}

inline ios_base& showbase(ios_base& _Iosbase)
{       // set showbase
  _Iosbase.setf(ios_base::showbase);
  return _Iosbase;
}

inline ios_base& showpoint(ios_base& _Iosbase)
{       // set showpoint
  _Iosbase.setf(ios_base::showpoint);
  return _Iosbase;
}

inline ios_base& showpos(ios_base& _Iosbase)
{       // set showpos
  _Iosbase.setf(ios_base::showpos);
  return _Iosbase;
}

inline ios_base& skipws(ios_base& _Iosbase)
{       // set skipws
  _Iosbase.setf(ios_base::skipws);
  return _Iosbase;
}

inline ios_base& unitbuf(ios_base& _Iosbase)
{       // set unitbuf
  _Iosbase.setf(ios_base::unitbuf);
  return _Iosbase;
}

inline ios_base& uppercase(ios_base& _Iosbase)
{       // set uppercase
  _Iosbase.setf(ios_base::uppercase);
  return _Iosbase;
}

#undef _GETLOC

} /* namespace std */

#endif /* _IOS_ */

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