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

#ifndef _SYSTEM_BUILD
  #pragma system_include
#endif

#include <istream>

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

namespace std {

#if _DLIB_FULL_LOCALE_SUPPORT
  #define _ISTR_GETLOC     _Istr.getloc()
#else
  #define _ISTR_GETLOC
#endif

// basic_string INSERTERS AND EXTRACTORS
template<class _Elem,
         class _Traits,
         class _Alloc> inline
basic_istream<_Elem, _Traits>& operator>>(
  basic_istream<_Elem, _Traits> && _Istr,
  basic_string<_Elem, _Traits, _Alloc>& _Str)
{       // extract a string
  typedef ctype<_Elem> _Ctype;
  typedef basic_istream<_Elem, _Traits> _Myis;
  typedef basic_string<_Elem, _Traits, _Alloc> _Mystr;
  typedef typename _Mystr::size_type _Mysizt;

  ios_base::iostate _State = ios_base::goodbit;
  bool _Changed = false;
  const typename _Myis::sentry _Ok(_Istr);

  if (_Ok)
  {       // state okay, extract characters
    const _Ctype& _Ctype_fac = use_facet< _Ctype >(_ISTR_GETLOC);
    _Str.erase();

    _TRY_IO_BEGIN
    _Mysizt _Size =      0 < _Istr.width()
                      && (_Mysizt)_Istr.width() < _Str.max_size()
                    ? (_Mysizt)_Istr.width()
                    : _Str.max_size();
    typename _Traits::int_type _Meta = _Istr.rdbuf()->sgetc();

    for (; 0 < _Size; --_Size, _Meta = _Istr.rdbuf()->snextc())
      if (_Traits::eq_int_type(_Traits::eof(), _Meta))
      {       // end of file, quit
        _State |= ios_base::eofbit;
        break;
      }
      else if (_Ctype_fac.is(_Ctype::space, _Traits::to_char_type(_Meta)))
        break;  // whitespace, quit
      else
      {       // add character to string
        _Str.append(1, _Traits::to_char_type(_Meta));
        _Changed = true;
      }
    _CATCH_IO_(_Istr)
  }

  _Istr.width(0);
  if (!_Changed)
    _State |= ios_base::failbit;
  _Istr.setstate(_State);
  return _Istr;
}

template<class _Elem,
         class _Traits,
         class _Alloc> inline
basic_istream<_Elem, _Traits>& getline(basic_istream<_Elem, _Traits> && _Istr,
                                       basic_string<_Elem, _Traits,
                                       _Alloc>& _Str, const _Elem _Delim)
{       // get characters into string, discard delimiter
  typedef basic_istream<_Elem, _Traits> _Myis;

  ios_base::iostate _State = ios_base::goodbit;
  bool _Changed = false;
  const typename _Myis::sentry _Ok(_Istr, true);

  if (_Ok)
  {       // state okay, extract characters
    _TRY_IO_BEGIN
    _Str.erase();
    const typename _Traits::int_type _Metadelim = _Traits::to_int_type(_Delim);
    typename _Traits::int_type _Meta = _Istr.rdbuf()->sgetc();

    for (; ; _Meta = _Istr.rdbuf()->snextc())
      if (_Traits::eq_int_type(_Traits::eof(), _Meta))
      {       // end of file, quit
        _State |= ios_base::eofbit;
        break;
      }
      else if (_Traits::eq_int_type(_Meta, _Metadelim))
      {       // got a delimiter, discard it and quit
        _Changed = true;
        _Istr.rdbuf()->sbumpc();
        break;
      }
      else if (_Str.max_size() <= _Str.size())
      {       // string too large, quit
        _State |= ios_base::failbit;
        break;
      }
      else
      {       // got a character, add it to string
        _Str += _Traits::to_char_type(_Meta);
        _Changed = true;
      }
    _CATCH_IO_(_Istr)
  }

  if (!_Changed)
    _State |= ios_base::failbit;
  _Istr.setstate(_State);
  return _Istr;
}

template<class _Elem,
         class _Traits,
         class _Alloc> inline
basic_istream<_Elem, _Traits>& getline(basic_istream<_Elem, _Traits> && _Istr,
                                     basic_string<_Elem, _Traits, _Alloc>& _Str)
{       // get characters into string, discard newline
  return getline(_Istr, _Str, _Istr.widen('\n'));
}

template<class _Elem,
         class _Traits,
         class _Alloc> inline
basic_istream<_Elem, _Traits>& operator>>(basic_istream<_Elem, _Traits>& _Istr,
                                     basic_string<_Elem, _Traits, _Alloc>& _Str)
{       // extract a string
  return std::move(_Istr) >> _Str;
}

template<class _Elem,
         class _Traits,
         class _Alloc> inline
basic_istream<_Elem, _Traits>& getline(basic_istream<_Elem, _Traits>& _Istr,
                                       basic_string<_Elem, _Traits,
                                       _Alloc>& _Str, const _Elem _Delim)
{       // get characters into string, discard delimiter
  return getline(std::move(_Istr), _Str, _Delim);
}

template<class _Elem,
         class _Traits,
         class _Alloc> inline
basic_istream<_Elem, _Traits>& getline(basic_istream<_Elem, _Traits>& _Istr,
                                       basic_string<_Elem, _Traits,
                                       _Alloc>& _Str)
{       // get characters into string, discard newline
  return getline(std::move(_Istr), _Str, _Istr.widen('\n'));
}

template<class _Elem,
         class _Traits,
         class _Alloc> inline
basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Ostr,
                                          const basic_string<_Elem, _Traits,
                                          _Alloc>& _Str)
{       // insert a string
  typedef basic_ostream<_Elem, _Traits> _Myos;
  typedef basic_string<_Elem, _Traits, _Alloc> _Mystr;
  typedef typename _Mystr::size_type _Mysizt;

  ios_base::iostate _State = ios_base::goodbit;
  _Mysizt _Size = _Str.size();
  _Mysizt _Pad =   _Ostr.width() <= 0 || (_Mysizt)_Ostr.width() <= _Size
                 ? 0
                 : (_Mysizt)_Ostr.width() - _Size;
  const typename _Myos::sentry _Ok(_Ostr);

  if (!_Ok)
    _State |= ios_base::badbit;
  else
  {       // state okay, insert characters
    _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(_Str.c_str(), (streamsize)_Size)
           != (streamsize)_Size)
      _State |= ios_base::badbit;
    else
      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;
}

// sto* NARROW CONVERSIONS
long stol(const string& _Str, size_t *_Idx = 0, int _Base = 10);
int stoi(const string& _Str, size_t *_Idx = 0, int _Base = 10);
unsigned long stoul(const string& _Str, size_t *_Idx = 0, int _Base = 10);
long long stoll(const string& _Str, size_t *_Idx = 0, int _Base = 10);
unsigned long long stoull(const string& _Str, size_t *_Idx = 0, int _Base = 10);
__SOFTFP
float stof(const string& _Str, size_t *_Idx = 0);
__SOFTFP
double stod(const string& _Str, size_t *_Idx = 0);
__SOFTFP
long double stold(const string& _Str, size_t *_Idx = 0);
// sto* WIDE CONVERSIONS
long stol(const wstring& _Str, size_t *_Idx = 0, int _Base = 10);
  int stoi(const wstring& _Str, size_t *_Idx = 0, int _Base = 10);
unsigned long stoul(const wstring& _Str, size_t *_Idx = 0, int _Base = 10);
long long stoll(const wstring& _Str, size_t *_Idx = 0, int _Base = 10);
unsigned long long stoull(const wstring& _Str, size_t *_Idx = 0,
                          int _Base = 10);
__SOFTFP
float stof(const wstring& _Str, size_t *_Idx = 0);
__SOFTFP
double stod(const wstring& _Str, size_t *_Idx = 0);
__SOFTFP
long double stold(const wstring& _Str, size_t *_Idx = 0);

// to_string NARROW CONVERSIONS
string to_string(int);
string to_string(unsigned int);
string to_string(long);
string to_string(unsigned long);
string to_string(long long);
string to_string(unsigned long long);
__SOFTFP
string to_string(float);
__SOFTFP
string to_string(double);
__SOFTFP
string to_string(long double);
wstring to_wstring(int);
wstring to_wstring(unsigned int);
wstring to_wstring(long);
wstring to_wstring(unsigned long);
wstring to_wstring(long long);
wstring to_wstring(unsigned long long);
__SOFTFP
wstring to_wstring(float);
__SOFTFP
wstring to_wstring(double);
__SOFTFP
wstring to_wstring(long double);

#undef _ISTR_GETLOC

} /* namespace std */

namespace std {

// basic_string LITERALS
inline namespace literals {
inline namespace string_literals {

#pragma diag_suppress = Pe2506

inline string operator "" s(const char *_Str, size_t _Len)
{	// construct literal from [_Str, _Str + _Len)
  return string(_Str, _Len);
}

inline wstring operator "" s(const wchar_t *_Str, size_t _Len)
{	// construct literal from [_Str, _Str + _Len)
  return wstring(_Str, _Len);
}

inline u16string operator "" s(const char16_t *_Str, size_t _Len)
{	// construct literal from [_Str, _Str + _Len)
  return u16string(_Str, _Len);
}

inline u32string operator "" s(const char32_t *_Str, size_t _Len)
{	// construct literal from [_Str, _Str + _Len)
  return u32string(_Str, _Len);
}

#pragma diag_default = Pe2506

} // inline namespace string_literals
} // inline namespace literals

} // namespace std

using namespace std::literals::string_literals;

#endif /* _STRING */

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