/***************************************************************************
 *
 * _traits.h - definition of the char_traits class template
 *
 * This is an internal header file used to implement the C++ Standard
 * Library. It should never be #included directly by a program.
 *
 * $Id: _traits.h 648752 2008-04-16 17:01:56Z faridz $
 *
 ***************************************************************************
 *
 * Licensed to the Apache Software  Foundation (ASF) under one or more
 * contributor  license agreements.  See  the NOTICE  file distributed
 * with  this  work  for  additional information  regarding  copyright
 * ownership.   The ASF  licenses this  file to  you under  the Apache
 * License, Version  2.0 (the  "License"); you may  not use  this file
 * except in  compliance with the License.   You may obtain  a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the  License is distributed on an  "AS IS" BASIS,
 * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
 * implied.   See  the License  for  the  specific language  governing
 * permissions and limitations under the License.
 *
 * Copyright 1994-2008 Rogue Wave Software, Inc.
 * 
 **************************************************************************/

#ifndef _RWSTD_RW_TRAITS_H_INCLUDED
#define _RWSTD_RW_TRAITS_H_INCLUDED

#ifndef _RWSTD_RW_IOSFWD_H_INCLUDED
#  include <rw/_iosfwd.h>
#endif   // _RWSTD_RW_IOSFWD_H_INCLUDED

#ifndef _RWSTD_RW_MBSTATE_H_INCLUDED
#  include <rw/_mbstate.h>   // for _RWSTD_MBSTATE_T
#endif   // _RWSTD_RW_MBSTATE_H_INCLUDED


#if defined (_RWSTDDEBUG) || defined (_RWSTD_EDG_ECCP)

// avoid including <cstring> and <cwchar> in debug mode or when using
// the vanilla EDG eccp (i.e., in strict conformance mode) to prevent
// namespace pollutiuon

_RWSTD_NAMESPACE (__rw) {

_RWSTD_EXPORT void* __rw_memcpy (void*, const void*, _RWSTD_SIZE_T);
_RWSTD_EXPORT void* __rw_memmove (void*, const void*, _RWSTD_SIZE_T);
_RWSTD_EXPORT const void* __rw_memchr (const void*, int, _RWSTD_SIZE_T);
_RWSTD_EXPORT void* __rw_memset (void*, int, _RWSTD_SIZE_T);
_RWSTD_EXPORT int __rw_memcmp (const void*, const void*, _RWSTD_SIZE_T);
_RWSTD_EXPORT _RWSTD_SIZE_T __rw_strlen (const char*);

#  ifndef _RWSTD_NO_WCHAR_T

_RWSTD_EXPORT wchar_t* __rw_wmemcpy (wchar_t*, const wchar_t*, _RWSTD_SIZE_T);
_RWSTD_EXPORT wchar_t* __rw_wmemmove (wchar_t*, const wchar_t*, _RWSTD_SIZE_T);
_RWSTD_EXPORT const wchar_t*
__rw_wmemchr (const wchar_t*, wchar_t, _RWSTD_SIZE_T);
_RWSTD_EXPORT wchar_t* __rw_wmemset (wchar_t*, wchar_t, _RWSTD_SIZE_T);
_RWSTD_EXPORT int __rw_wmemcmp (const wchar_t*, const wchar_t*, _RWSTD_SIZE_T);
_RWSTD_EXPORT _RWSTD_SIZE_T __rw_wcslen (const wchar_t*);

#  endif   // _RWSTD_NO_WCHAR_T

}   // namespace __rw

#  define _RWSTD_MEMCPY    _RW::__rw_memcpy
#  define _RWSTD_MEMCMP    _RW::__rw_memcmp
#  define _RWSTD_MEMCHR    _RW::__rw_memchr
#  define _RWSTD_MEMMOVE   _RW::__rw_memmove
#  define _RWSTD_MEMSET    _RW::__rw_memset
#  define _RWSTD_STRLEN    _RW::__rw_strlen

#  define _RWSTD_WMEMCPY   _RW::__rw_wmemcpy
#  define _RWSTD_WMEMCMP   _RW::__rw_wmemcmp
#  define _RWSTD_WMEMCHR   _RW::__rw_wmemchr
#  define _RWSTD_WMEMMOVE  _RW::__rw_wmemmove
#  define _RWSTD_WMEMSET   _RW::__rw_wmemset
#  define _RWSTD_WCSLEN    _RW::__rw_wcslen
#else   // if !defined (_RWSTDDEBUG) && !defined (_RWSTD_EDG_ECCP)

#  if 4 <= __GNUG__ && !defined (__INTEL_COMPILER)
     // use gcc 4.x intrinsic functions
#    define _RWSTD_MEMCPY    __builtin_memcpy
#    define _RWSTD_MEMCMP    __builtin_memcmp
#    define _RWSTD_MEMMOVE   __builtin_memmove
#    define _RWSTD_MEMSET    __builtin_memset
#    define _RWSTD_STRLEN    __builtin_strlen

#    if 4 < __GNUG__ || 3 <= __GNUC_MINOR__
       // __builtin_memchr() is only available in gcc 4.3 and beyond
#      define _RWSTD_MEMCHR    __builtin_memchr
#    else   // gcc < 4.3
#      include _RWSTD_CSTRING   // for memchr()
#      define _RWSTD_MEMCHR    _RWSTD_C::memchr
#    endif   // gcc 4.3
#  else   // gcc < 4.0
#    include _RWSTD_CSTRING   // for memcmp(), ...

#    define _RWSTD_MEMCPY    _RWSTD_C::memcpy
#    define _RWSTD_MEMCMP    _RWSTD_C::memcmp
#    define _RWSTD_MEMMOVE   _RWSTD_C::memmove
#    define _RWSTD_MEMSET    _RWSTD_C::memset
#    define _RWSTD_STRLEN    _RWSTD_C::strlen
#    define _RWSTD_MEMCHR    _RWSTD_C::memchr
#  endif   // gcc 4.0

#  include _RWSTD_CWCHAR    // wmemcmp(), ...

#  ifndef _RWSTD_NO_WMEMCPY
#    define _RWSTD_WMEMCPY   _RWSTD_C::wmemcpy
#  elif !defined (_RWSTD_NO_WCHAR_T)

_RWSTD_NAMESPACE (__rw) {

_RWSTD_EXPORT wchar_t*
__rw_wmemcpy (wchar_t*, const wchar_t*, _RWSTD_SIZE_T);


}   // namespace __rw

#    define _RWSTD_WMEMCPY   _RW::__rw_wmemcpy
#  endif   // _RWSTD_NO_WMEMCPY

#  ifndef _RWSTD_NO_WMEMCMP
#    define _RWSTD_WMEMCMP   wmemcmp
#  elif !defined (_RWSTD_NO_WCHAR_T)

_RWSTD_NAMESPACE (__rw) {

_RWSTD_EXPORT int
__rw_wmemcmp (const wchar_t*, const wchar_t*, _RWSTD_SIZE_T);


}   // namespace __rw

#    define _RWSTD_WMEMCMP   _RW::__rw_wmemcmp
#  endif   // _RWSTD_NO_WMEMCMP

#  ifndef _RWSTD_NO_WMEMMOVE
#    define _RWSTD_WMEMMOVE  _RWSTD_C::wmemmove
#  elif !defined (_RWSTD_NO_WCHAR_T)

_RWSTD_NAMESPACE (__rw) {

_RWSTD_EXPORT wchar_t*
__rw_wmemmove (wchar_t*, const wchar_t*, _RWSTD_SIZE_T);


}   // namespace __rw

#    define _RWSTD_WMEMMOVE   _RW::__rw_wmemmove
#  endif   // _RWSTD_NO_WMEMMOVE

#  ifndef _RWSTD_NO_WMEMSET
#    define _RWSTD_WMEMSET   _RWSTD_C::wmemset
#  elif !defined (_RWSTD_NO_WCHAR_T)

_RWSTD_NAMESPACE (__rw) {

_RWSTD_EXPORT wchar_t*
__rw_wmemset (wchar_t*, wchar_t, _RWSTD_SIZE_T);


}   // namespace __rw

#    define _RWSTD_WMEMSET   _RW::__rw_wmemset
#  endif   // _RWSTD_NO_WMEMSET

#  ifndef _RWSTD_NO_WCSLEN
#    define _RWSTD_WCSLEN    _RWSTD_C::wcslen
#  elif !defined (_RWSTD_NO_WCHAR_T)

_RWSTD_NAMESPACE (__rw) {

_RWSTD_EXPORT _RWSTD_SIZE_T
__rw_wcslen (const wchar_t*);


}   // namespace __rw

#    define _RWSTD_WCSLEN   _RW::__rw_wcslen
#  endif   // _RWSTD_NO_WCSLEN

#  ifndef _RWSTD_NO_WMEMCHR
#    define _RWSTD_WMEMCHR   _RWSTD_C::wmemchr
#  elif !defined (_RWSTD_NO_WCHAR_T)

_RWSTD_NAMESPACE (__rw) {

_RWSTD_EXPORT const wchar_t*
__rw_wmemchr (const wchar_t*, wchar_t, _RWSTD_SIZE_T);


}   // namespace __rw

#    define _RWSTD_WMEMCHR   _RW::__rw_wmemchr
#  endif   // _RWSTD_NO_WMEMCHR

#endif   // !_RWSTDDEBUG && !(vanilla EDG eccp demo)


_RWSTD_NAMESPACE (std) { 


// 27.4.1, p2
// the C++ type ptrdiff_t is the same as the POSIX ssize_t suggested
// to be used here in 27.4.2, Footnote 266, except for Win64 where
// the former is 64 bits while the latter is only 32 bits wide
typedef _RWSTD_PTRDIFF_T streamsize;


// 27.4.3
template <class _StateT>
class fpos
{
public:

    typedef _StateT state_type;
      
#ifndef _RWSTD_NO_POD_ZERO_INIT

    fpos (_RWSTD_STREAMOFF __off = 0,
          const state_type &__state = state_type ())
        : _C_pos (__off),
          _C_state (__state)
        { }

#else   // if defined (_RWSTD_NO_POD_ZERO_INIT)

    fpos (_RWSTD_STREAMOFF __off = 0)
        : _C_pos (__off) {
        _RWSTD_MEMSET (&_C_state, 0, sizeof _C_state);
    }

    fpos (_RWSTD_STREAMOFF __off, const state_type &__state)
        : _C_pos (__off),
          _C_state (__state)
        { }

#endif   // _RWSTD_NO_POD_ZERO_INIT

    operator _RWSTD_STREAMOFF () const {
        return _C_pos;
    }

    // 27.4.3.1, p1
    void state (state_type __state) {
        _C_state = __state;
    }

    // 27.4.3.1, p2
    state_type state () const {
        return _C_state;
    }

    // 27.4.3.2, p1: Table 88
    fpos& operator-= (_RWSTD_STREAMOFF __off) {
        return _C_pos -= __off, *this;
    }

    fpos& operator+= (_RWSTD_STREAMOFF __off) {
        return _C_pos += __off, *this;
    }

    fpos operator- (_RWSTD_STREAMOFF __off) const {
        return fpos (*this) -= __off;
    }

    fpos operator+ (_RWSTD_STREAMOFF __off) const {
        return fpos (*this) += __off;
    }

    // equality and relational operators provided
    // via the conversion operator to streamoff

private:

    _RWSTD_STREAMOFF _C_pos;     // signed displacement
    state_type       _C_state;   // conversion state
};


template <class  _CharT> 
struct char_traits;


#ifndef _RWSTD_NO_EXT_CHAR_TRAITS_PRIMARY

template <class  _CharT> 
struct char_traits
{
    typedef _CharT           char_type;
    typedef int              int_type;
    typedef _RWSTD_STREAMOFF off_type;
    typedef _RWSTD_MBSTATE_T state_type;
    typedef fpos<state_type> pos_type;

    static int_type eof () {
        return -1;
    }

    static void assign (char_type& __c1, const char_type& __c2) {
        __c1 = __c2;
    }

    static bool eq (const char_type& __c1, const char_type& __c2) {
        return __c1 == __c2;
    }

    static bool lt (const char_type& __c1, const char_type& __c2) {
        return __c1 < __c2;
    }

    static int
    compare (const char_type* __s1, const char_type* __s2, _RWSTD_SIZE_T __n) {
        for (_RWSTD_SIZE_T __i = 0; __i != __n; ++__i) {
            if (!eq (__s1[__i], __s2[__i])) {
                return lt (__s1[__i], __s2[__i]) ? -1 : 1;
            }
        }
        return 0;
    }
        
    static _RWSTD_SIZE_T length (const char_type *__s) {
        _RWSTD_SIZE_T __len = 0;
        while (!eq (*__s++, char_type ()))
            ++__len;
        return __len;
    }
 
    static const char_type* 
    find (const char_type* __s, _RWSTD_SIZE_T __n, const char_type& __c) {
        while (__n-- > 0 && !eq (*__s, __c) )
            ++__s;
        return  eq (*__s, __c) ? __s : 0;
    }

    static char_type*
    move (char_type* __s1, const char_type* __s2, _RWSTD_SIZE_T __n) {
        _RWSTD_MEMMOVE (__s1, __s2, __n * sizeof (char_type));
        return __s1;
    }

    static char_type*
    copy (char_type *__dst, const char_type *__src, _RWSTD_SIZE_T __n) {
        _RWSTD_MEMCPY (_RWSTD_STATIC_CAST (void*, __dst),
                       _RWSTD_STATIC_CAST (const void*, __src),
                       __n * sizeof (char_type));
        return __dst;
    }

    static char_type*
    assign (char_type* __s, _RWSTD_SIZE_T __n, char_type __c) {
        char_type* __tmp = __s;
        while (__n-- > 0) 
            assign (*__tmp++, __c);
        return __s;
    }

    static bool eq_int_type (const int_type& __c1, const int_type& __c2) {
        return __c1 == __c2;
    }

    static int_type not_eof (const int_type& __c) {
        return eq_int_type (eof (), __c) ? 0 : __c;
    }

    static char_type to_char_type (const int_type& __c) {
        // cast to prevent warnings for unusual types
        return _RWSTD_STATIC_CAST (char_type, __c);
    }
      
    static int_type to_int_type (const char_type& __c) {
        // cast to prevent warnings for unusual types
        return _RWSTD_STATIC_CAST (int_type, __c);
    }
};

#endif   // _RWSTD_NO_EXT_CHAR_TRAITS_PRIMARY


// 21.1.3.1
_RWSTD_SPECIALIZED_CLASS  
struct char_traits<char> 
{
    typedef char             char_type;
    typedef _RWSTD_INT_T     int_type;
    typedef _RWSTD_STREAMOFF off_type; 
    typedef _RWSTD_MBSTATE_T state_type;
    typedef fpos<state_type> pos_type;

    static int_type eof () {
        return int_type (_RWSTD_EOF);
    }

    static void assign (char_type& __c1, const char_type& __c2){
        __c1 = __c2;
    }

    static bool eq (const char_type& __c1, const char_type& __c2) {
        return __c1 == __c2;
    }

    static bool lt (const char_type& __c1, const char_type& __c2) {
        // lwg issue 467: cast arguments to unsigned char
        // to get the same result as memcmp(&c1, &c2) < 0
        return   _RWSTD_STATIC_CAST (unsigned char, __c1)
               < _RWSTD_STATIC_CAST (unsigned char, __c2);
    }

    static int
    compare (const char_type* __s1, const char_type* __s2, _RWSTD_SIZE_T __n) {
        return _RWSTD_MEMCMP (__s1, __s2, __n);
    }

    static const char_type*
    find (const char_type* __s, _RWSTD_SIZE_T __n, const char_type& __c) {
        // cast to const void* used to get around a gcc 2.95 bug
        // that prevents a static_cast from void* --> const T*
        // (only occurs if memchr() isn't overloaded on const)
        return _RWSTD_STATIC_CAST (
            const char_type*, (const void*)_RWSTD_MEMCHR (
                __s, _RWSTD_STATIC_CAST (unsigned char, __c), __n));
    }

    static _RWSTD_SIZE_T length (const char_type *__s) {
        return _RWSTD_STRLEN (__s);
    }

    static char_type*
    move (char_type* __s1, const char_type* __s2, _RWSTD_SIZE_T __n) {
        _RWSTD_MEMMOVE (__s1, __s2, __n);
        return __s1;
    }

    static char_type*
    copy (char_type *__dst, const char_type *__src, _RWSTD_SIZE_T __n) {
        _RWSTD_MEMCPY (__dst, __src, __n);
        return __dst;
    }

    static char_type*
    assign (char_type* __s, _RWSTD_SIZE_T __n, char_type __c) {
        _RWSTD_MEMSET (__s, __c, __n);
        return __s;
    }

    static bool eq_int_type (const int_type& __c1, const int_type& __c2) {
        return __c1 == __c2;
    }

    static int_type not_eof (const int_type& __c) {
        return eq_int_type (eof (), __c) ? 0 : __c;
    }
                        
    static char_type to_char_type (const int_type& __c) {
        return _RWSTD_STATIC_CAST (char_type, __c);
    }
      
    static int_type to_int_type (const char_type& __c) {
        // make sure (signed char)'\xff' converts to 255 and not -1
        return _RWSTD_STATIC_CAST (unsigned char, __c);
    }
};


#ifndef _RWSTD_NO_WCHAR_T

// 21.1.3.2
_RWSTD_SPECIALIZED_CLASS  
struct char_traits<wchar_t> 
{
    typedef wchar_t          char_type;
    typedef _RWSTD_WINT_T    int_type;
    typedef _RWSTD_STREAMOFF off_type;
    typedef _RWSTD_MBSTATE_T state_type;
    typedef fpos<state_type> pos_type;

    static int_type eof () {
        return int_type (_RWSTD_WEOF);
    }

    static void assign (char_type& __c1, const char_type& __c2) {
        __c1 = __c2;
    }

    static bool eq (const char_type& __c1, const char_type& __c2) {
        return __c1 == __c2;
    }

    static bool lt (const char_type& __c1, const char_type& __c2) {
        return __c1 < __c2;
    }

    static int
    compare (const char_type* __s1, const char_type* __s2, _RWSTD_SIZE_T __n) {
        return _RWSTD_WMEMCMP (__s1, __s2, __n);
    }

    static _RWSTD_SIZE_T length (const char_type *__s) {
        // [harmless] cast necessary on CygWin
        return _RWSTD_WCSLEN (_RWSTD_CONST_CAST (char_type*, __s));
    }
      
    static const char_type*
    find (const char_type* __s, _RWSTD_SIZE_T __n, const char_type& __c) {
        // const cast in case of a const-incorrect wmemchr()
        return _RWSTD_STATIC_CAST (const char_type*,
                   _RWSTD_WMEMCHR (_RWSTD_CONST_CAST (char_type*, __s),
                                   __c, __n));
    }

    static char_type*
    copy (char_type *__dst, const char_type *__src, _RWSTD_SIZE_T __n) {
        _RWSTD_WMEMCPY (__dst, __src, __n);
        return __dst;
    }
      
    static char_type*
    move (char_type* __s1, const char_type* __s2, _RWSTD_SIZE_T __n) {
        _RWSTD_WMEMMOVE (__s1, __s2, __n);
        return __s1;
    }

    static char_type*
    assign (char_type* __s, _RWSTD_SIZE_T __n, char_type __c) {
        _RWSTD_WMEMSET (__s, __c, __n);
        return __s;
    }

    static bool eq_int_type (const int_type& __c1, const int_type& __c2) {
        return __c1 == __c2;
    }

    static int_type not_eof (const int_type& __c) {
        return eq_int_type (eof (), __c) ? 0 : __c;
    }

    static char_type to_char_type (const int_type& __c) {
        return __c;
    }
      
    static int_type to_int_type (const char_type& __c) {
        return __c;
    }
};

#endif   // _RWSTD_NO_WCHAR_T


}   // namespace std


#endif   // _RWSTD_RW_TRAITS_H_INCLUDED
