/***************************************************************************
 *
 * _ctype.h
 *
 * This is an internal header file used to implement the C++ Standard
 * Library. It should never be #included directly by a program.
 *
 * $Id: _ctype.h 649680 2008-04-18 20:18:52Z 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 2001-2005 Rogue Wave Software.
 * 
 **************************************************************************/

#ifndef _RWSTD_LOC_CTYPE_H_INCLUDED
#define _RWSTD_LOC_CTYPE_H_INCLUDED


#include <loc/_facet.h>
#include <rw/_bitmask.h>
#include <rw/_defs.h>

_RWSTD_NAMESPACE (__rw) { 

struct __rw_ctype_t;

enum __rw_ctype_mask {
    __rw_none   = 0,
    __rw_space  = 0x0001,
    __rw_print  = 0x0002,
    __rw_cntrl  = 0x0004,
    __rw_upper  = 0x0008,
    __rw_lower  = 0x0010,
    __rw_alpha  = 0x0020,
    __rw_digit  = 0x0040,
    __rw_punct  = 0x0080,
    __rw_xdigit = 0x0100,
    __rw_alnum  = __rw_alpha | __rw_digit,
    __rw_graph  = 0x0200,
    __rw_all    = 0x03ff
};

_RWSTD_DEFINE_BITMASK_OPERATORS (__rw_ctype_mask);

}   // namespace __rw


_RWSTD_NAMESPACE (std) { 

struct _RWSTD_CLASS_EXPORT locale;

// 22.2.1
struct _RWSTD_EXPORT ctype_base
{
    // 22.2.1, p1 - mask is a bitmask type (see 17.3.3.1.2)
    typedef _RWSTD_BITMASK_ENUM (_RW::__rw_ctype_mask) mask;

    _RWSTD_STATIC_CONST (mask, space  = _RW::__rw_space);
    _RWSTD_STATIC_CONST (mask, print  = _RW::__rw_print);
    _RWSTD_STATIC_CONST (mask, cntrl  = _RW::__rw_cntrl);
    _RWSTD_STATIC_CONST (mask, upper  = _RW::__rw_upper);
    _RWSTD_STATIC_CONST (mask, lower  = _RW::__rw_lower);
    _RWSTD_STATIC_CONST (mask, alpha  = _RW::__rw_alpha);
    _RWSTD_STATIC_CONST (mask, digit  = _RW::__rw_digit);
    _RWSTD_STATIC_CONST (mask, punct  = _RW::__rw_punct);
    _RWSTD_STATIC_CONST (mask, xdigit = _RW::__rw_xdigit);
    _RWSTD_STATIC_CONST (mask, alnum  = _RW::__rw_alnum);
    _RWSTD_STATIC_CONST (mask, graph  = _RW::__rw_graph);
};


// 22.2.1.1
_EXPORT
template <class _CharT>
class ctype;


#ifndef _RWSTD_NO_EXT_CTYPE_PRIMARY

_EXPORT
template <class _CharT>
class ctype: public _RW::__rw_facet, public ctype_base
{
public:

    typedef _CharT char_type;

    _EXPLICIT ctype (_RWSTD_SIZE_T __ref = 0)
        : _RW::__rw_facet (__ref) { }


    // 22.2.1.1.1, p1
    bool is (mask __m, char_type __c) const {
        return do_is ( __m, __c);
    }

    const char_type*
    is (const char_type* __lo, const char_type *__hi, mask *__vec) const {
        return do_is (__lo, __hi, __vec);
    }

    // 22.2.1.1.1, p2
    const char_type*
    scan_is (mask __m, const char_type *__lo, const char_type *__hi) const {
        return do_scan_is ( __m, __lo, __hi);
    }

    // 22.2.1.1.1, p3
    const char_type*
    scan_not (mask __m, const char_type *__lo, const char_type *__hi) const {
        return do_scan_not ( __m, __lo, __hi);
    }

    // 22.2.1.1.1, p4
    char_type (toupper)(char_type __c) const {
        return do_toupper (__c);
    }

    const char_type* (toupper)(char_type *__lo, const char_type *__hi) const {
        return do_toupper (__lo, __hi);
    }

    // 22.2.1.1.1, p5
    char_type (tolower)(char_type __c) const {
        return do_tolower (__c);
    }

    const char_type* (tolower)(char_type *__lo, const char_type *__hi) const {
        return do_tolower (__lo, __hi);
    }

    // 22.2.1.1.1, p6
    char_type widen (char __c) const {
        return do_widen (__c);
    }

    const char*
    widen (const char *__lo, const char *__hi, char_type *__to) const {
        return do_widen (__lo, __hi, __to);
    }

    // 22.2.1.1.1, p7
    char narrow (char_type __c, char __dfault) const {
        return do_narrow (__c, __dfault);
    }

    const char_type*
    narrow (const char_type *__lo, const char_type *__hi,
            char __dfault, char *__to) const {
        return do_narrow (__lo, __hi, __dfault, __to);
    }

    static _RW::__rw_facet_id id;

protected:

    // 22.2.1.1.2, p1
    virtual bool do_is (mask, char_type) const {
        return false;
    }

    virtual const char_type*
    do_is (const char_type*, const char_type*, mask*) const;

    // 22.2.1.1.2, p3
    virtual const char_type*
    do_scan_is (mask, const char_type*, const char_type*) const;

    // 22.2.1.1.2, p5
    virtual const char_type*
    do_scan_not (mask, const char_type*, const char_type*) const;

    // 22.2.1.1.2, p7
    virtual char_type do_toupper (char_type __c) const {
        return __c;
    }

    virtual const char_type*
    do_toupper (char_type*, const char_type*) const;

    // 22.2.1.1.2, p9
    virtual char_type do_tolower (char_type __c) const {
        return __c;
    }

    virtual const char_type*
    do_tolower (char_type*, const char_type*) const;

    // 22.2.1.1.2, p11
    virtual char_type do_widen (char) const {
        return char_type ();
    }

    virtual const char*
    do_widen (const char*, const char*, char_type*) const;

    // 22.2.1.1.2, p13
    virtual char do_narrow (char_type, char __dfault) const {
        return __dfault;
    }

    virtual const char_type*
    do_narrow (const char_type*, const char_type*, char, char*) const;
};

#endif   // _RWSTD_NO_EXT_CTYPE_PRIMARY


_RWSTD_SPECIALIZED_CLASS
class _RWSTD_EXPORT ctype<char>: public _RW::__rw_facet, public ctype_base
{
    typedef unsigned char _UChar;

public:

    typedef char char_type;

    bool is (mask __m, char_type __c) const {
#if _RWSTD_UCHAR_MAX <= 255
        return (_C_mask_tab [_UChar (__c)] & __m) != 0;
#else
        return __c < table_size && (_C_mask_tab [_UChar (__c)] & __m) != 0;
#endif
    }

    _RWSTD_STATIC_CONST (_RWSTD_SIZE_T, table_size = 256);

    _EXPLICIT ctype (const mask* = 0, bool = false, _RWSTD_SIZE_T = 0);

    const char_type* is (const char_type*, const char_type*, mask*) const;

    const char_type* scan_is (mask, const char_type*, const char_type*) const;

    const char_type* scan_not (mask, const char_type*, const char_type*) const;

    char_type (toupper)(char_type __c) const {
        return do_toupper (__c);
    }

    char_type (tolower)(char_type __c) const {
        return do_tolower (__c);
    }

    // 22.2.1.1.1, p6
    char_type widen (char) const;

    char narrow (char_type, char) const;

    const char_type* (toupper)(char_type *__lo, const char_type *__hi) const {
        return do_toupper (__lo, __hi);
    }

    const char_type* (tolower)(char_type *__lo, const char_type *__hi) const {
        return do_tolower (__lo, __hi);
    }

    const char_type*
    widen (const char *__lo, const char *__hi, char_type *__to) const {
        return do_widen (__lo, __hi, __to);
    }

    const char_type*
    narrow (const char_type *__lo, const char_type *__hi,
            char_type __dfault, char_type *__to) const {
        return do_narrow (__lo, __hi, __dfault, __to);
    }

    static _RW::__rw_facet_id id;

protected:

    const mask* table () const _THROWS (()) {
        return _C_mask_tab;
    }

    static const mask* classic_table () _THROWS (());

    virtual ~ctype ();

    virtual const char_type*
    do_toupper (char_type*, const char_type*) const;

    virtual const char_type*
    do_tolower (char_type*, const char_type*) const; 

    virtual char_type do_toupper (char_type) const;

    virtual char_type do_tolower (char_type) const;

    virtual char_type do_widen (char) const;

    virtual const char_type*
    do_widen (const char_type*, const char_type*, char_type*) const;

    virtual char_type do_narrow (char_type, char_type) const;

    virtual const char_type*
    do_narrow (const char_type*, const char_type*, char_type, char_type*)const;

protected:

    const mask    *_C_mask_tab;         // mask for each character
    unsigned char *_C_upper_tab;        // uppercase version of each character
    unsigned char *_C_lower_tab;        // lowercase version of each character
    char           _C_narrow_tab [256]; // cached results of do_narrow()
    char           _C_wide_tab [256];   // cached results of do_widen()
    int            _C_delete_it;        // delete tables above?
};


inline ctype<char>::char_type
ctype<char>::narrow (char_type __c, char __dfault) const
{
    const _RWSTD_SIZE_T __inx = _RWSTD_STATIC_CAST (unsigned char, __c);

    // optimize away all but the first call to the virtual do_widen()

    if (

#if _RWSTD_CHAR_BIT > 8

        __inx < sizeof _C_narrow_tab / sizeof *_C_narrow_tab &&

#endif   // _RWSTD_CHAR_BIT > 8

        _C_narrow_tab [__inx])
        return _C_narrow_tab [__inx];

    // template argument provided to work around an HP aCC bug (PR #27087)
    ctype<char>* const __self = _RWSTD_CONST_CAST (ctype<char>*, this);

    __c = do_narrow (__c, __dfault);

    if (__c != __dfault)
        __self->_C_narrow_tab [__inx] = __c;

    return __c;
}


inline ctype<char>::char_type
ctype<char>::widen (char __ch) const
{
    const _RWSTD_SIZE_T __inx = _RWSTD_STATIC_CAST (unsigned char, __ch);

    // optimize away all but the first call to the virtual do_widen()

#if _RWSTD_CHAR_BIT <= 8
    const bool __fits = true;
#else
    const bool __fits = __inx < sizeof _C_wide_tab / sizeof *_C_wide_tab;
#endif

    if (__fits) {
        if (_C_wide_tab [__inx])
            return _C_wide_tab [__inx];

        // template argument provided to work around an HP aCC bug (PR #27087)
        ctype<char>* const __self = _RWSTD_CONST_CAST (ctype<char>*, this);

        return __self->_C_wide_tab [__inx] = do_widen (__ch);
    }
    else
        return do_widen (__ch);
}


// 22.2.1.2
template <class _CharT>
class ctype_byname: public ctype<_CharT>
{
    char _C_namebuf [32];

public:

    _EXPLICIT ctype_byname (const char *__name, _RWSTD_SIZE_T __ref = 0)
        : ctype<_CharT>(__ref) {
        this->_C_set_name (__name, _C_namebuf, sizeof _C_namebuf);
    }
};


_RWSTD_SPECIALIZED_CLASS
class _RWSTD_EXPORT ctype_byname<char>: public ctype<char>
{
    char _C_namebuf [32];

public:

    _EXPLICIT ctype_byname (const char*, _RWSTD_SIZE_T = 0);
};


#ifndef _RWSTD_NO_WCHAR_T

_RWSTD_SPECIALIZED_CLASS
class _RWSTD_EXPORT ctype<wchar_t>: public _RW::__rw_facet, public ctype_base
{
    typedef unsigned char _UChar;

    enum { _C_tab_size = 256 };

public:

    typedef wchar_t char_type;

    _EXPLICIT ctype (_RWSTD_SIZE_T = 0);

    // 22.2.1.1.1, p1
    bool is (mask __m, char_type __c) const {
        return do_is ( __m, __c);
    }

    const char_type*
    is (const char_type *__lo, const char_type *__hi, mask *__vec) const {
        return do_is (__lo, __hi, __vec);
    }

    // 22.2.1.1.1, p2
    const char_type*
    scan_is (mask __m, const char_type *__lo, const char_type *__hi) const {
        return do_scan_is ( __m, __lo, __hi);
    }

    // 22.2.1.1.1, p3
    const char_type*
    scan_not (mask __m, const char_type *__lo, const char_type *__hi) const {
        return do_scan_not ( __m, __lo, __hi);
    }

    // 22.2.1.1.1, p4
    char_type (toupper)(char_type __c) const {
        return do_toupper (__c);
    }

    const char_type* (toupper)(char_type *__lo, const char_type *__hi) const {
        return do_toupper (__lo, __hi);
    }

    // 22.2.1.1.1, p5
    char_type (tolower)(char_type __c) const {
        return do_tolower (__c);
    }

    const char_type* (tolower)(char_type *__lo, const char_type *__hi) const {
        return do_tolower (__lo, __hi);
    }

    // 22.2.1.1.1, p6
    char_type widen (char) const;

    const char*
    widen (const char* __lo, const char *__hi, char_type *__to) const {
        return do_widen (__lo, __hi, __to);
    }

    // 22.2.1.1.1, p7
    char narrow (char_type, char) const;

    const char_type*
    narrow (const char_type *__lo, const char_type *__hi,
            char __dfault, char *__to) const {
        return do_narrow (__lo, __hi, __dfault, __to);
    }

    static _RW::__rw_facet_id id;

protected:

    virtual ~ctype ();

    // 22.2.1.1.2, p1
    virtual bool do_is (mask, char_type) const;

    virtual const char_type*
    do_is (const char_type*, const char_type*, mask*) const;

    // 22.2.1.1.2, p7
    virtual char_type do_toupper (char_type) const;

    // 22.2.1.1.2, p9
    virtual char_type do_tolower (char_type) const;

    // 22.2.1.1.2, p11
    virtual char_type do_widen (char) const;

    virtual const char*
    do_widen (const char*, const char*, char_type*) const;

    // 22.2.1.1.2, p13
    virtual char
    do_narrow (char_type, char) const;

    virtual const char_type*
    do_toupper (char_type*, const char_type*) const;

    virtual const char_type*
    do_tolower (char_type*, const char_type*) const;

    // 22.2.1.1.2, p3
    virtual const char_type*
    do_scan_is (mask, const char_type*, const char_type*) const;

    // 22.2.1.1.2, p5
    virtual const char_type*
    do_scan_not (mask, const char_type*, const char_type*) const;

    virtual const char_type*
    do_narrow (const char_type*, const char_type*, char, char*) const;

private:

    friend class ctype_byname<wchar_t>;

    const mask      *_C_mask_tab;         // mask for each character
    unsigned char   *_C_upper_tab;        // uppercase version of each character
    unsigned char   *_C_lower_tab;        // lowercase version of each character
    char             _C_narrow_tab [256]; // cached results of do_narrow()
    char_type        _C_wide_tab [256];   // cached results of do_widen()
    int              _C_delete_it;        // delete tables above?
};


inline char
ctype<wchar_t>::narrow (char_type __c, char __dfault) const
{
    const _RWSTD_SIZE_T __inx = _RWSTD_STATIC_CAST (_RWSTD_UWCHAR_INT_T, __c);

    // optimize away all but the first call to the virtual do_widen()
    if (   __inx < sizeof _C_narrow_tab / sizeof *_C_narrow_tab
        && _C_narrow_tab [__inx])
        return _C_narrow_tab [__inx];

    // template argument provided to work around an HP aCC bug (PR #27087)
    ctype<wchar_t>* const __self = _RWSTD_CONST_CAST (ctype<wchar_t>*, this);

    const char __ch = do_narrow (__c, __dfault);

    if (__inx < sizeof _C_narrow_tab / sizeof *_C_narrow_tab && __ch != __dfault)
        __self->_C_narrow_tab [__inx] = __ch;

    return __ch;
}


inline ctype<wchar_t>::char_type
ctype<wchar_t>::widen (char __ch) const
{
    const _RWSTD_SIZE_T __inx = _RWSTD_STATIC_CAST (unsigned char, __ch);

    // optimize away all but the first call to the virtual do_widen()

#if _RWSTD_CHAR_BIT <= 8
    const bool __fits = true;
#else
    const bool __fits = __inx < sizeof _C_wide_tab / sizeof *_C_wide_tab;
#endif

    if (__fits) {
        if (_C_wide_tab [__inx])
            return _C_wide_tab [__inx];

        // template argument provided to work around an HP aCC bug (PR #27087)
        ctype<wchar_t>* const __self = _RWSTD_CONST_CAST (ctype<wchar_t>*, this);

        return __self->_C_wide_tab [__inx] = do_widen (__ch);
    }
    else
        return do_widen (__ch);
}



_RWSTD_SPECIALIZED_CLASS
class _RWSTD_EXPORT ctype_byname<wchar_t>: public ctype<wchar_t>
{
public:

    _EXPLICIT ctype_byname (const char*, _RWSTD_SIZE_T = 0);

protected:

    virtual ~ctype_byname ();

    virtual bool
    do_is (mask, char_type) const;

    virtual const char_type*
    do_is (const char_type*, const char_type*, mask*) const;

    virtual char_type
    do_toupper (char_type) const;

    virtual const char_type*
    do_toupper (char_type*, const char_type*) const;

    virtual char_type
    do_tolower (char_type) const;

    virtual const char_type*
    do_tolower (char_type*, const char_type*) const;

    virtual const char_type*
    do_scan_is (mask, const char_type*, const char_type*) const;

    virtual const char_type*
    do_scan_not (mask, const char_type*, const char_type*) const;
    
    virtual char
    do_narrow(char_type, char) const;

    virtual const char_type*
    do_narrow (const char_type*, const char_type*, char, char*) const;

    virtual char_type do_widen (char) const;
 
    virtual const char*
    do_widen (const char*, const char*, char_type*) const;

private:

    char           _C_namebuf [32];
    const void    *_C_cvtimpl;     // codecvt database mapped by ctype facet
    _RWSTD_SIZE_T  _C_cvtsize;     // size of the above mapping
};

#endif   // _RWSTD_NO_WCHAR_T


}   // namespace std


#if _RWSTD_DEFINE_TEMPLATE (CTYPE)
#  include <loc/_ctype.cc>
#endif   // _RWSTD_DEFINE_TEMPLATE (CTYPE)


#endif   // _RWSTD_LOC_CTYPE_H_INCLUDED
