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

#ifndef _SYSTEM_BUILD
#pragma system_include
#endif

#include <cstdio>
#include <cstring>
#if _DLIB_WIDE_CHARACTERS
#include <cwchar>
#endif
#include <xstddef>

namespace std {

// STREAM POSITIONING TYPES (from <streambuf>)

#define _FSEEK_OFF(str, off, way)      (long)fseek(str, (long)(off), way)

typedef long streamoff;
typedef int streamsize;

_DLIB_DATA_ATTR extern fpos_t _Fpz;
_DLIB_CONST_ATTR extern const streamoff _BADOFF;

// TEMPLATE CLASS fpos (from <streambuf>)
template<class _Statetype>
class fpos
{       // store arbitrary file position
  typedef fpos<_Statetype> _Myt;

public:
  fpos(streamoff _Off = 0)
    : _Myoff(_Off), _Fpos(_Fpz), _Mystate()
  {       // construct with stream offset
  }

  fpos(_Statetype _State, fpos_t _Fileposition)
    : _Myoff(0), _Fpos(_Fileposition), _Mystate(_State)
  {       // construct with conversion state and C file position
  }

  _Statetype state() const
  {       // return conversion state
    return _Mystate;
  }

  void state(_Statetype _State)
  {       // set conversion state
    _Mystate = _State;
  }

  fpos_t seekpos() const
  {       // return C file position
    return _Fpos;
  }

  operator streamoff() const
  {       // return offset
    return (streamoff)(_Myoff + _FPOSOFF(_Fpos));
  }

  streamoff operator-(const _Myt& _Right) const
  {       // return difference of file positions as an offset
    return (streamoff)*this - (streamoff)_Right;
  }

  _Myt& operator+=(streamoff _Off)
  {       // add offset
    _Myoff += _Off;
    return *this;
  }

  _Myt& operator-=(streamoff _Off)
  {       // subtract offset
    _Myoff -= _Off;
    return *this;
  }

  _Myt operator+(streamoff _Off) const
  {       // return this + offset
    _Myt _Tmp = *this;
    return _Tmp += _Off;
  }

  _Myt operator-(streamoff _Off) const
  {       // return this - offset
    _Myt _Tmp = *this;
    return _Tmp -= _Off;
  }

  bool operator==(const _Myt& _Right) const
  {       // test for file position equality
    return (streamoff)*this == (streamoff)_Right;
  }

  bool operator==(streamoff _Right) const
  {       // test for file position equality with streamoff
    return (streamoff)*this == _Right;
  }

  bool operator!=(const _Myt& _Right) const
  {       // test for file position inequality
    return !(*this == _Right);
  }

private:
  streamoff _Myoff;       // stream offset
  fpos_t _Fpos;   // C file position
  _Statetype _Mystate;    // current conversion state
};

#define _POS_TYPE_FROM_STATE(postype, state, position) postype(state, position)
#define _POS_TYPE_TO_FPOS_T(pos)       pos.seekpos()
#define _POS_TYPE_TO_STATE(pos)        pos.state()

typedef fpos<_Mbstatet> streampos;

typedef streampos wstreampos;

// TEMPLATE STRUCT _Char_traits (FROM <string>)
template<class _Elem,
         class _Int_type>
struct _Char_traits
{       // properties of a string or stream element
  typedef _Elem char_type;
  typedef _Int_type int_type;
  typedef streampos pos_type;
  typedef streamoff off_type;
  typedef _Mbstatet state_type;

  _NOINLINE static int compare(const _Elem *_First1,
                               const _Elem *_First2, size_t _Count)
  {       // compare [_First1, _First1 + _Count) with [_First2, ...)
    for (; 0 < _Count; --_Count, ++_First1, ++_First2)
      if (!eq(*_First1, *_First2))
        return lt(*_First1, *_First2) ? -1 : +1;
    return 0;
  }

  _NOINLINE static size_t length(const _Elem *_First)
  {       // find length of null-terminated sequence
    size_t _Count;
    for (_Count = 0; !eq(*_First, _Elem()); ++_First)
      ++_Count;
    return _Count;
  }

  _NOINLINE static _Elem *copy(_Elem *_First1,
                               const _Elem *_First2, size_t _Count)
  {       // copy [_First2, _First2 + _Count) to [_First1, ...)
    _Elem *_Next = _First1;
    for (; 0 < _Count; --_Count, ++_Next, ++_First2)
      assign(*_Next, *_First2);
    return _First1;
  }

  _NOINLINE static const _Elem *find(const _Elem *_First,
                                     size_t _Count, const _Elem& _Ch)
  {       // look for _Ch in [_First, _First + _Count)
    for (; 0 < _Count; --_Count, ++_First)
      if (eq(*_First, _Ch))
        return _First;
    return 0;
  }

  _NOINLINE static _Elem *move(_Elem *_First1,
                               const _Elem *_First2, size_t _Count)
  {       // copy [_First2, _First2 + _Count) to [_First1, ...)
    _Elem *_Next = _First1;
    if (_First2 < _Next && _Next < _First2 + _Count)
      for (_Next += _Count, _First2 += _Count; 0 < _Count; --_Count)
        assign(*--_Next, *--_First2);
    else
      for (; 0 < _Count; --_Count, ++_Next, ++_First2)
        assign(*_Next, *_First2);
    return _First1;
  }

  _NOINLINE static _Elem *assign(_Elem *_First,
                                 size_t _Count, _Elem _Ch)
  {       // assign _Count * _Ch to [_First, ...)
    _Elem *_Next = _First;
    for (; 0 < _Count; --_Count, ++_Next)
      assign(*_Next, _Ch);
    return _First;
  }

  static void assign(_Elem& _Left, const _Elem& _Right) _NOEXCEPT
  {       // assign an element
    _Left = _Right;
  }

  static constexpr bool eq(const _Elem& _Left,
                           const _Elem& _Right) _NOEXCEPT
  {       // test for element equality
    return _Left == _Right;
  }

  static constexpr bool lt(const _Elem& _Left,
                           const _Elem& _Right) _NOEXCEPT
  {       // test if _Left precedes _Right
    return _Left < _Right;
  }

  static constexpr _Elem to_char_type(const int_type& _Meta) _NOEXCEPT
  {       // convert metacharacter to character
    return (_Elem)_Meta;
  }

  static constexpr int_type to_int_type(const _Elem& _Ch) _NOEXCEPT
  {       // convert character to metacharacter
    return (int_type)_Ch;
  }

  static constexpr bool eq_int_type(const int_type& _Left,
                                     const int_type& _Right) _NOEXCEPT
  {       // test for metacharacter equality
    return _Left == _Right;
  }

  static constexpr int_type not_eof(const int_type& _Meta) _NOEXCEPT
  {       // return anything but EOF
    return _Meta != eof() ? (int_type)_Meta : (int_type)!eof();
  }

  static constexpr int_type eof() _NOEXCEPT
  {       // return end-of-file metacharacter
    return (int_type)EOF;
  }
};

// TEMPLATE STRUCT char_traits
template<class _Elem>
struct char_traits
  : public _Char_traits<_Elem, long>
{       // properties of a string or stream unknown element
};

// STRUCT char_traits<char16_t>
template<>
struct char_traits<char16_t>
  : public _Char_traits<char16_t, unsigned short>
{       // properties of a string or stream char16_t element
};

typedef streampos u16streampos;

// STRUCT char_traits<char32_t>
template<>
struct char_traits<char32_t>
  : public _Char_traits<char32_t, __UINT_LEAST32_T_TYPE__>
{       // properties of a string or stream char32_t element
};

typedef streampos u32streampos;

#if _DLIB_WIDE_CHARACTERS
// STRUCT char_traits<wchar_t>
template<>
struct char_traits<wchar_t>
{       // properties of a string or stream wchar_t element
  typedef wchar_t _Elem;
  typedef _Elem char_type;        // for overloads
  typedef wint_t int_type;
  typedef streampos pos_type;
  typedef streamoff off_type;
  typedef _Mbstatet state_type;

  static int compare(const _Elem *_First1, const _Elem *_First2,
                     size_t _Count)
  {       // compare [_First1, _First1 + _Count) with [_First2, ...)
    return ::wmemcmp(_First1, _First2, _Count);
  }

  static size_t length(const _Elem *_First)
  {       // find length of null-terminated sequence
    return ::wcslen(_First);
  }

  static _Elem *copy(_Elem *_First1, const _Elem *_First2,
                     size_t _Count)
  {       // copy [_First2, _First2 + _Count) to [_First1, ...)
    return (_Elem *)::wmemcpy(_First1, _First2, _Count);
  }

  static const _Elem *find(const _Elem *_First, size_t _Count,
                           const _Elem& _Ch)
  {       // look for _Ch in [_First, _First + _Count)
    return (const _Elem *)::wmemchr(_First, _Ch, _Count);
  }

  static _Elem *move(_Elem *_First1, const _Elem *_First2,
                     size_t _Count)
  {       // copy [_First2, _First2 + _Count) to [_First1, ...)
    return (_Elem *)::wmemmove(_First1, _First2, _Count);
  }

  static _Elem *assign(_Elem *_First, size_t _Count,
                       _Elem _Ch)
  {       // assign _Count * _Ch to [_First, ...)
    return (_Elem *)::wmemset(_First, _Ch, _Count);
  }

  static void assign(_Elem& _Left, const _Elem& _Right) _NOEXCEPT
  {       // assign an element
    _Left = _Right;
  }

  static constexpr bool eq(const _Elem& _Left,
                           const _Elem& _Right) _NOEXCEPT
  {       // test for element equality
    return _Left == _Right;
  }

  static constexpr bool lt(const _Elem& _Left,
                           const _Elem& _Right) _NOEXCEPT
  {       // test if _Left precedes _Right
    return _Left < _Right;
  }

  static constexpr _Elem to_char_type(const int_type& _Meta) _NOEXCEPT
  {       // convert metacharacter to character
    return _Meta;
  }

  static constexpr int_type to_int_type(const _Elem& _Ch) _NOEXCEPT
  {       // convert character to metacharacter
    return _Ch;
  }

  static constexpr bool eq_int_type(const int_type& _Left,
                                    const int_type& _Right) _NOEXCEPT
  {       // test for metacharacter equality
    return _Left == _Right;
  }

  static constexpr int_type not_eof(const int_type& _Meta) _NOEXCEPT
  {       // return anything but EOF
    return _Meta != eof() ? _Meta : !eof();
  }

  static constexpr int_type eof() _NOEXCEPT
  {       // return end-of-file metacharacter
    return WEOF;
  }
};
#endif

// STRUCT char_traits<char> (FROM <string>)
template<> struct char_traits<char>
{       // properties of a string or stream char element
  typedef char _Elem;
  typedef _Elem char_type;
  typedef int int_type;
  typedef streampos pos_type;
  typedef streamoff off_type;
  typedef _Mbstatet state_type;

  static int compare(const _Elem *_First1, const _Elem *_First2,
                     size_t _Count)
  {       // compare [_First1, _First1 + _Count) with [_First2, ...)
    return ::memcmp(_First1, _First2, _Count);
  }

  static size_t length(const _Elem *_First)
  {       // find length of null-terminated string
    return ::strlen(_First);
  }

  static _Elem *copy(_Elem *_First1, const _Elem *_First2,
                     size_t _Count)
  {       // copy [_First2, _First2 + _Count) to [_First1, ...)
    return (_Elem *)::memcpy(_First1, _First2, _Count);
  }

  static const _Elem *find(const _Elem *_First, size_t _Count,
                           const _Elem& _Ch)
  {       // look for _Ch in [_First, _First + _Count)
    return (const _Elem *)::memchr(_First, _Ch, _Count);
  }

  static _Elem *move(_Elem *_First1, const _Elem *_First2,
                     size_t _Count)
  {       // copy [_First2, _First2 + _Count) to [_First1, ...)
    return (_Elem *)::memmove(_First1, _First2, _Count);
  }

  static _Elem *assign(_Elem *_First, size_t _Count,
                       _Elem _Ch)
  {       // assign _Count * _Ch to [_First, ...)
    return (_Elem *)::memset(_First, _Ch, _Count);
  }

  static void assign(_Elem& _Left, const _Elem& _Right) _NOEXCEPT
  {       // assign an element
    _Left = _Right;
  }

  static constexpr bool eq(const _Elem& _Left,
                           const _Elem& _Right) _NOEXCEPT
  {       // test for element equality
    return _Left == _Right;
  }

  static constexpr bool lt(const _Elem& _Left,
                            const _Elem& _Right) _NOEXCEPT
  {       // test if _Left precedes _Right
    return (unsigned char)_Left < (unsigned char)_Right;
  }

  static constexpr _Elem to_char_type(const int_type& _Meta) _NOEXCEPT
  {       // convert metacharacter to character
    return (_Elem)_Meta;
  }

  static constexpr int_type to_int_type(const _Elem& _Ch) _NOEXCEPT
  {       // convert character to metacharacter
    return (unsigned char)_Ch;
  }

  static constexpr bool eq_int_type(const int_type& _Left,
                                    const int_type& _Right) _NOEXCEPT
  {       // test for metacharacter equality
    return _Left == _Right;
  }

  static constexpr int_type not_eof(const int_type& _Meta) _NOEXCEPT
  {       // return anything but EOF
    return _Meta != eof() ? _Meta : !eof();
  }

  static constexpr int_type eof() _NOEXCEPT
  {       // return end-of-file metacharacter
    return EOF;
  }
};

// FORWARD REFERENCES
template<class _Ty>
class allocator;
class ios_base;
template<class _Elem,
         class _Traits = char_traits<_Elem> >
class basic_ios;
template<class _Elem,
         class _Traits = char_traits<_Elem> >
class istreambuf_iterator;
template<class _Elem,
         class _Traits = char_traits<_Elem> >
class ostreambuf_iterator;
template<class _Elem,
         class _Traits = char_traits<_Elem> >
class basic_streambuf;
template<class _Elem,
         class _Traits = char_traits<_Elem> >
class basic_istream;
template<class _Elem,
         class _Traits = char_traits<_Elem> >
class basic_ostream;
template<class _Elem,
         class _Traits = char_traits<_Elem> >
class basic_iostream;
template<class _Elem,
         class _Traits = char_traits<_Elem>,
         class _Alloc = allocator<_Elem> >
class basic_stringbuf;
template<class _Elem,
         class _Traits = char_traits<_Elem>,
         class _Alloc = allocator<_Elem> >
class basic_istringstream;
template<class _Elem,
         class _Traits = char_traits<_Elem>,
         class _Alloc = allocator<_Elem> >
class basic_ostringstream;
template<class _Elem,
         class _Traits = char_traits<_Elem>,
         class _Alloc = allocator<_Elem> >
class basic_stringstream;
template<class _Elem,
         class _Traits = char_traits<_Elem> >
class basic_filebuf;
template<class _Elem,
         class _Traits = char_traits<_Elem> >
class basic_ifstream;
template<class _Elem,
         class _Traits = char_traits<_Elem> >
class basic_ofstream;
template<class _Elem,
         class _Traits = char_traits<_Elem> >
class basic_fstream;

// char TYPEDEFS
#pragma preferred_typedef
typedef basic_ios<char, char_traits<char> > ios;
#pragma preferred_typedef
typedef basic_streambuf<char, char_traits<char> > streambuf;
#pragma preferred_typedef
typedef basic_istream<char, char_traits<char> > istream;
#pragma preferred_typedef
typedef basic_ostream<char, char_traits<char> > ostream;
#pragma preferred_typedef
typedef basic_iostream<char, char_traits<char> > iostream;
#pragma preferred_typedef
typedef basic_stringbuf<char, char_traits<char>,
                        allocator<char> > stringbuf;
#pragma preferred_typedef
typedef basic_istringstream<char, char_traits<char>,
                            allocator<char> > istringstream;
#pragma preferred_typedef
typedef basic_ostringstream<char, char_traits<char>,
                            allocator<char> > ostringstream;
#pragma preferred_typedef
typedef basic_stringstream<char, char_traits<char>,
                           allocator<char> > stringstream;
#pragma preferred_typedef
typedef basic_filebuf<char, char_traits<char> > filebuf;
#pragma preferred_typedef
typedef basic_ifstream<char, char_traits<char> > ifstream;
#pragma preferred_typedef
typedef basic_ofstream<char, char_traits<char> > ofstream;
#pragma preferred_typedef
typedef basic_fstream<char, char_traits<char> > fstream;

// wchat_t TYPEDEFS
#pragma preferred_typedef
typedef basic_ios<wchar_t, char_traits<wchar_t> > wios;
#pragma preferred_typedef
typedef basic_streambuf<wchar_t, char_traits<wchar_t> > wstreambuf;
#pragma preferred_typedef
typedef basic_istream<wchar_t, char_traits<wchar_t> > wistream;
#pragma preferred_typedef
typedef basic_ostream<wchar_t, char_traits<wchar_t> > wostream;
#pragma preferred_typedef
typedef basic_iostream<wchar_t, char_traits<wchar_t> > wiostream;
#pragma preferred_typedef
typedef basic_stringbuf<wchar_t, char_traits<wchar_t>,
                        allocator<wchar_t> > wstringbuf;
#pragma preferred_typedef
typedef basic_istringstream<wchar_t, char_traits<wchar_t>,
                            allocator<wchar_t> > wistringstream;
#pragma preferred_typedef
typedef basic_ostringstream<wchar_t, char_traits<wchar_t>,
                            allocator<wchar_t> > wostringstream;
#pragma preferred_typedef
typedef basic_stringstream<wchar_t, char_traits<wchar_t>,
                           allocator<wchar_t> > wstringstream;
#pragma preferred_typedef
typedef basic_filebuf<wchar_t, char_traits<wchar_t> > wfilebuf;
#pragma preferred_typedef
typedef basic_ifstream<wchar_t, char_traits<wchar_t> > wifstream;
#pragma preferred_typedef
typedef basic_ofstream<wchar_t, char_traits<wchar_t> > wofstream;
#pragma preferred_typedef
typedef basic_fstream<wchar_t, char_traits<wchar_t> > wfstream;

} /* namespace std */

#endif /* _IOSFWD_ */

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