stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject svn commit: r420234 - in /incubator/stdcxx/trunk/tests: include/rw_ctype.h self/0.ctype.cpp src/ctype.cpp
Date Sun, 09 Jul 2006 00:47:26 GMT
Author: sebor
Date: Sat Jul  8 17:47:25 2006
New Revision: 420234

URL: http://svn.apache.org/viewvc?rev=420234&view=rev
Log:
2006-07-08  Martin Sebor  <sebor@roguewave.com>

	STDCXX-3
	* rw_ctype.h: New header with the definitions of the UserCtype
	primary template and explicit specializations for char, wchar_t,
	and UserChar.
	* ctype.cpp: Definitions of members of UserCtype specializations.
	* test/ctype.cpp: New test (partially) exercising UserCtype::is().

Added:
    incubator/stdcxx/trunk/tests/include/rw_ctype.h   (with props)
    incubator/stdcxx/trunk/tests/self/0.ctype.cpp   (with props)
    incubator/stdcxx/trunk/tests/src/ctype.cpp   (with props)

Added: incubator/stdcxx/trunk/tests/include/rw_ctype.h
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/include/rw_ctype.h?rev=420234&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/include/rw_ctype.h (added)
+++ incubator/stdcxx/trunk/tests/include/rw_ctype.h Sat Jul  8 17:47:25 2006
@@ -0,0 +1,323 @@
+/**************************************************************************
+ *
+ * rw_ctype.h - defines a User Defined ctype facet
+ *
+ * $Id$
+ *
+ ***************************************************************************
+ *
+ * Copyright 2006 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Licensed 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.
+ * 
+ **************************************************************************/
+
+#ifndef RW_CTYPE_H_INCLUDED
+#define RW_CTYPE_H_INCLUDED
+
+
+#include <locale>      // for ctype, locale
+#include <rw_char.h>   // for UserChar
+#include <testdefs.h>
+
+
+struct _TEST_EXPORT UserCtypeBase: std::ctype_base
+{
+    enum MemFunc {
+        mf_is,
+        mf_is_range,
+        mf_scan_is,
+        mf_scan_not,
+        mf_toupper,
+        mf_toupper_range,
+        mf_tolower, 
+        mf_tolower_range,
+        mf_widen,
+        mf_widen_range,
+        mf_narrow,
+        mf_narrow_range,
+        n_funs
+    };
+
+    struct Exception {
+        virtual ~Exception ();
+        virtual const char* what () const = 0;
+    };
+
+    // name of the character type ("char", "wchar_t", "UserChar")
+    const char* const cname_;
+
+    // array of masks corresponding to each of the characters in chars
+    // the first negative element in chars denotes the last element
+    const int* masks_;
+    const int* chars_;
+
+    // arrays of correspondning uppercase and lowercase characters
+    const int* upper_;
+    const int* lower_;
+
+    // arrays of corresponding narrow and wide characters
+    const int* narrow_;
+    const int* wide_;
+
+    // counter of the number of calls to all member functions
+    // made throughout the lifetime of this object
+    _RWSTD_SIZE_T n_all_calls_;
+
+    // counter of the number of calls to each member function
+    // made throughout the lifetime of this object
+    _RWSTD_SIZE_T n_calls_ [n_funs];
+
+    // counter of the number of exceptions thrown by each member
+    // function throughout the lifetime of this object
+    _RWSTD_SIZE_T n_throws_ [n_funs];
+
+    // member function counter value that, when reached, will
+    // cause an exception to be thrown
+    _RWSTD_SIZE_T throw_at_calls_ [n_funs];
+
+    // value of a character that, when encountered, will cause
+    // an exception to be thrown
+    int throw_char_;
+
+    // when true the facet throws an exception when it encounters
+    // an invalid character (unless otherwise specified)
+    bool throw_on_invalid_;
+
+protected:
+
+    UserCtypeBase (const char*);
+
+private:
+
+    UserCtypeBase (const UserCtypeBase&);    // not CopyConstructible
+    void operator= (const UserCtypeBase&);   // not Assignable
+};
+
+
+template <class _CharT>
+class UserCtype;
+
+
+_RWSTD_SPECIALIZED_CLASS
+class _TEST_EXPORT UserCtype<char>
+    : public std::ctype<char>, public UserCtypeBase
+{
+    typedef std::ctype<char_type> Base;
+
+public:
+
+    explicit
+    UserCtype (const int* = 0, const int* = 0, _RWSTD_SIZE_T = 0);
+
+protected:
+
+    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 char_type
+    do_widen (char) const;
+
+    virtual const char*
+    do_widen (const char*, const char*, 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;
+};
+
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+_RWSTD_SPECIALIZED_CLASS
+class _TEST_EXPORT UserCtype<wchar_t>
+    : public std::ctype<wchar_t>, public UserCtypeBase
+{
+    typedef std::ctype<char_type> Base;
+
+public:
+
+    explicit
+    UserCtype (const int* = 0, const int* = 0, _RWSTD_SIZE_T = 0);
+
+protected:
+
+    virtual bool
+    do_is (mask, char_type) const;
+
+    virtual const char_type*
+    do_is (const char_type*, const char_type*, mask*) 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_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 char_type
+    do_widen (char) const;
+
+    virtual const char*
+    do_widen (const char*, const char*, 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;
+};
+
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+
+_RWSTD_SPECIALIZED_CLASS
+class _TEST_EXPORT UserCtype<UserChar>
+    : public std::locale::facet, public UserCtypeBase
+{
+    typedef std::locale::facet Base;
+public:
+
+    typedef UserChar char_type;
+
+    explicit
+    UserCtype (const int* = 0, const int* = 0, _RWSTD_SIZE_T = 0);
+
+    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);
+    }
+
+    const char_type*
+    scan_is (mask m, const char_type *lo, const char_type *hi) const {
+        return do_scan_is ( m, lo, hi);
+    }
+
+    const char_type*
+    scan_not (mask m, const char_type *lo, const char_type *hi) const {
+        return do_scan_not (m, lo, hi);
+    }
+
+    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);
+    }
+
+    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);
+    }
+
+    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);
+    }
+
+    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 std::locale::id id;
+
+protected:
+
+    virtual bool
+    do_is (mask, char_type) const;
+
+    virtual const char_type*
+    do_is (const char_type*, const char_type*, mask*) 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_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 c) const;
+
+    virtual const char_type*
+    do_tolower (char_type*, const char_type*) const;
+
+    virtual char_type
+    do_widen (char) const;
+
+    virtual const char*
+    do_widen (const char*, const char*, char_type*) const;
+
+    virtual char
+    do_narrow (char_type, char dfault) const;
+
+    virtual const char_type*
+    do_narrow (const char_type*, const char_type*, char, char*) const;
+};
+
+
+#endif   // RW_CTYPE_H_INCLUDED

Propchange: incubator/stdcxx/trunk/tests/include/rw_ctype.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/tests/include/rw_ctype.h
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/stdcxx/trunk/tests/self/0.ctype.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/self/0.ctype.cpp?rev=420234&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/self/0.ctype.cpp (added)
+++ incubator/stdcxx/trunk/tests/self/0.ctype.cpp Sat Jul  8 17:47:25 2006
@@ -0,0 +1,473 @@
+/************************************************************************
+ *
+ * 0.ctype.cpp - test exercising the UserCtype helper class template
+ *
+ * $Id$
+ *
+ ************************************************************************
+ *
+ * Copyright 2006 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Copyright 2006 Rogue Wave Software.
+ *
+ * Licensed 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.
+ *
+ **************************************************************************/
+
+#include <rw_char.h>     // for UserChar
+#include <rw_ctype.h>    // for UserCtype
+#include <rw_printf.h>   // for rw_printf
+#include <driver.h>
+
+#include <stdlib.h>      // for free()
+#include <string.h>      // for memset(), size_t, strlen()
+
+/***********************************************************************/
+
+extern const char
+cntrl[] = {
+
+#if 'A' == 0x41   // ASCII
+    "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+    "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x7f"
+#elif 'A' == 0xc1   // EBCDIC
+    ""
+#endif
+
+};
+
+extern const std::size_t
+n_cntrl = sizeof cntrl - 1;
+
+extern const char
+digits[] = "0123456789";
+
+extern const std::size_t
+n_digits = sizeof digits - 1;
+
+extern const char
+graph[] = "!\"#$%&\\()*+,-./0123456789:;<=>?@[]^_`{|}~";
+
+extern const std::size_t
+n_graph = sizeof graph - 1;
+
+extern const char
+lower[] = "abcdefghijklmnopqrstuvwxyz";
+
+extern const std::size_t
+n_lower = sizeof lower - 1;
+
+extern const char
+punct[] = "!#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~";
+
+extern const std::size_t
+n_punct = sizeof punct - 1;
+
+extern const char
+print[] = {
+    "!\"#$%&\\()*+,-./0123456789:;<=>?@[]^_`{|}~"
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+    "abcdefghijklmnopqrstuvwxyz"
+};
+
+extern const std::size_t
+n_print = sizeof print - 1;
+
+extern const char
+spaces[] = " \t\v\f\r\n";
+
+extern const std::size_t
+n_spaces = sizeof spaces - 1;
+
+extern const char
+upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+extern const std::size_t
+n_upper = sizeof upper - 1;
+
+extern const char
+xdigits[] = "0123456789ABCDEFabcdef";
+
+extern const std::size_t
+n_xdigits = sizeof xdigits - 1;
+
+/***********************************************************************/
+
+template <class charT>
+void
+test_is (charT*, const char *cname,
+         std::ctype_base::mask m,
+         const char *chars, std::size_t n_chars)
+{
+    UserCtype<charT> ctp;
+
+    std::size_t n_calls  = ctp.n_calls_ [ctp.mf_is];
+    std::size_t n_throws = ctp.n_throws_ [ctp.mf_is];
+
+    std::size_t expect_calls  = 0;
+    std::size_t expect_throws = 0;
+
+    for (std::size_t i = 0; i != n_chars; ++i) {
+        const charT ch = make_char (chars [i], (charT*)0);
+
+        int result = -1;
+
+#ifndef _RWSTD_NO_EXCEPTIONS
+
+        // let the first call call succeed and trigger an exception
+        // on the second call to UserCtype::is()
+        ctp.throw_at_calls_ [ctp.mf_is] =
+            ctp.n_calls_ [ctp.mf_is] + 2;
+
+        for (int j = 0; j != 2; ++j) {
+
+            if (1 < sizeof (charT)) {
+                // can only count UserCtype<charT>::is() calls when
+                // charT != char since there is no virtual do_is()
+                // in the char explicit specialization
+                ++expect_calls;
+            }
+            else if (j) {
+                // cannot induce an exception out of UserCtype<char>::is()
+                // since there is no virtual do_is() in the specialization
+                break;
+            }
+
+            if (j)
+                ++expect_throws;
+
+            int threw = 0;
+
+            try {
+                result = ctp.is (m, ch);
+            }
+            catch (...) {
+                threw = 1;
+            }
+
+            rw_assert (j == threw, 0, __LINE__,
+                       "UserCtype<%s>::is(%{LC}, %{#c}) "
+                       "%{?}unexpectedly threw%{:}failed to throw%{;}",
+                       cname, m, ch, j == threw);
+        }
+
+#else   // if defined (_RWSTD_NO_EXCEPTIONS)
+
+        ++expect_calls;
+        result = ctp.is (m, ch);
+
+#endif   // _RWSTD_NO_EXCEPTIONS
+
+        rw_assert (result, 0, __LINE__,
+                   "UserCtype<%s>::is(%{LC}, %{#c}) == true",
+                   cname, m, chars [i]);
+    }
+
+    n_calls = ctp.n_calls_ [ctp.mf_is] - n_calls;
+
+    rw_assert (expect_calls == n_calls, 0, __LINE__,
+               "expected %zu calls to UserCtype<%s>::is(%{LC}, char_type), "
+               "got %zu", expect_calls, cname, m, n_calls);
+
+    n_throws = ctp.n_throws_ [ctp.mf_is] - n_throws;
+
+    rw_assert (expect_throws == n_throws, 0, __LINE__,
+               "expected %zu exceptions thrown by UserCtype<%s>::is(%{LC}, "
+               "char_type), got %zu", expect_throws, cname, m, n_throws);
+}
+
+template <class charT>
+void
+test_is (charT*, const char *cname)
+{
+    rw_info (0, 0, __LINE__, "UserCtype<%s>::is"
+             "(mask, char_type) const", cname);
+
+    //////////////////////////////////////////////////////////////////
+    // exercise default behavior
+
+    test_is ((charT*)0, cname, std::ctype_base::alnum,  lower,   n_lower);
+    test_is ((charT*)0, cname, std::ctype_base::alnum,  upper,   n_upper);
+    test_is ((charT*)0, cname, std::ctype_base::alnum,  digits,  n_digits);
+    test_is ((charT*)0, cname, std::ctype_base::alnum,  xdigits, n_xdigits);
+    test_is ((charT*)0, cname, std::ctype_base::alpha,  lower,   n_lower);
+    test_is ((charT*)0, cname, std::ctype_base::alpha,  upper,   n_upper);
+    test_is ((charT*)0, cname, std::ctype_base::cntrl,  cntrl,   n_cntrl);
+    test_is ((charT*)0, cname, std::ctype_base::digit,  digits,  n_digits);
+    test_is ((charT*)0, cname, std::ctype_base::graph,  graph,   n_graph);
+    test_is ((charT*)0, cname, std::ctype_base::lower,  lower,   n_lower);
+    test_is ((charT*)0, cname, std::ctype_base::print,  print,   n_print);
+    test_is ((charT*)0, cname, std::ctype_base::punct,  punct,   n_punct);
+    test_is ((charT*)0, cname, std::ctype_base::space,  spaces,  n_spaces);
+    test_is ((charT*)0, cname, std::ctype_base::xdigit, xdigits, n_xdigits);
+
+    //////////////////////////////////////////////////////////////////
+    // exercise custom behavior
+
+    static const int chars[] = {
+        '0', '1', '2', '3', 'a', 'b', 'c',
+        0x100, 0x7fff, 0x8000, 0xffff,
+#if 2 < _RWSTD_INT_SIZE
+        0x10000, 0x7fffffff, 0x80000000, 0xffffffff,
+#else
+        0x1ff, 0x700, 0x8fff, 0xf000,
+#endif
+        -1   // end of chars
+    };
+
+    static const int masks[] = {
+        /* '0'        */ std::ctype_base::alpha,
+        /* '1'        */ std::ctype_base::cntrl,
+        /* '2'        */ std::ctype_base::digit,
+        /* '3'        */ std::ctype_base::lower,
+        /* 'a'        */ std::ctype_base::print,
+        /* 'b'        */ std::ctype_base::punct,
+        /* 'c'        */ std::ctype_base::space,
+        /* 0x100      */ std::ctype_base::upper,
+        /* 0x7fff     */ std::ctype_base::xdigit,
+        /* 0x8000     */ std::ctype_base::alpha | std::ctype_base::cntrl,
+        /* 0xffff     */ std::ctype_base::cntrl | std::ctype_base::digit,
+        /* 0x10000    */ std::ctype_base::digit | std::ctype_base::lower,
+        /* 0x7fffffff */ std::ctype_base::lower | std::ctype_base::print,
+        /* 0x80000000 */ std::ctype_base::print | std::ctype_base::punct,
+        /* 0xffffffff */ std::ctype_base::punct | std::ctype_base::space,
+        -1            // end of masks
+    };
+
+    static const int mask_all = 
+          std::ctype_base::alpha
+        | std::ctype_base::cntrl
+        | std::ctype_base::digit
+        | std::ctype_base::lower
+        | std::ctype_base::print
+        | std::ctype_base::punct
+        | std::ctype_base::space
+        | std::ctype_base::upper
+        | std::ctype_base::xdigit;
+
+    const UserCtype<charT> cust (chars, masks);
+
+    for (std::size_t i = 0; 0 <= chars [i]; ++i) {
+
+        // FIXME: enable tests of characters greater than CHAR_MAX
+        if (   _RWSTD_UCHAR_MAX < std::size_t (chars [i])
+            /* && sizeof (char) == sizeof (charT) */) {
+            // when charT == char break out when the character
+            // value is greater than CHAR_MAX
+            break;
+        }
+
+        const charT ch = make_char (chars [i], (charT*)0);
+
+        const std::ctype_base::mask m_is =
+            std::ctype_base::mask (masks [i]);
+
+        rw_assert (cust.is (m_is, ch),
+                   0, __LINE__,
+                   "UserCtype<%s>::is(%{LC}, %{#lc}) == true",
+                   cname, m_is, chars [i]);
+
+        const std::ctype_base::mask m_not =
+            std::ctype_base::mask (~m_is & mask_all);
+
+        rw_assert (!cust.is (m_not, ch), 0, __LINE__,
+                   "UserCtype<%s>::is(%{LC}, %{#lc}) == false",
+                   cname, m_not, chars [i]);
+    }
+}
+
+/***********************************************************************/
+
+template <class charT>
+void
+test_scan_is (charT*, const char *cname)
+{
+    rw_info (0, 0, __LINE__, "UserCtype<%s>::scan_is"
+             "(mask, const char_type*, const char_type*) const", cname);
+
+    rw_warn (0, 0, __LINE__, "UserCtype<%s>::scan_is"
+             "(mask, const char_type*, const char_type*) const"
+             " not exercised", cname);
+}
+
+/***********************************************************************/
+
+template <class charT>
+void
+test_scan_not (charT*, const char *cname)
+{
+    rw_info (0, 0, __LINE__, "UserCtype<%s>::scan_not"
+             "(mask, const char_type*, const char_type*) const", cname);
+
+    rw_warn (0, 0, __LINE__, "UserCtype<%s>::scan_not"
+             "(mask, const char_type*, const char_type*) const "
+             "not exercised", cname);
+}
+
+/***********************************************************************/
+
+template <class charT>
+void
+test_toupper (charT*, const char *cname)
+{
+    rw_info (0, 0, __LINE__, "UserCtype<%s>::toupper"
+             "(char_type) const", cname);
+
+    rw_warn (0, 0, __LINE__, "UserCtype<%s>::toupper"
+             "(char_type) const not exercised", cname);
+
+    rw_info (0, 0, __LINE__, "UserCtype<%s>::toupper"
+             "(char_type*, const char_type) const", cname);
+
+    rw_warn (0, 0, __LINE__, "UserCtype<%s>::toupper"
+             "(char_type*, const char_type) const not exercised", cname);
+}
+
+/***********************************************************************/
+
+template <class charT>
+void
+test_tolower (charT*, const char *cname)
+{
+    rw_info (0, 0, __LINE__, "UserCtype<%s>::tolower"
+             "(char_type) const", cname);
+
+    rw_warn (0, 0, __LINE__, "UserCtype<%s>::tolower"
+             "(char_type) const not exercised", cname);
+
+    rw_info (0, 0, __LINE__, "UserCtype<%s>::tolower"
+             "(char_type*, const char_type) const", cname);
+
+    rw_warn (0, 0, __LINE__, "UserCtype<%s>::tolower"
+             "(char_type*, const char_type) const not exercised", cname);
+}
+
+/***********************************************************************/
+
+template <class charT>
+void
+test_widen (charT*, const char *cname)
+{
+    rw_info (0, 0, __LINE__, "UserCtype<%s>::widen"
+             "(char) const", cname);
+
+    rw_warn (0, 0, __LINE__, "UserCtype<%s>::widen"
+             "(char) const not exercised", cname);
+
+    rw_info (0, 0, __LINE__, "UserCtype<%s>::widen"
+             "(const char*, const char*, char_type*) const", cname);
+
+    rw_warn (0, 0, __LINE__, "UserCtype<%s>::widen"
+             "(const char*, const char*, char_type*) const not exercised",
+             cname);
+}
+
+/***********************************************************************/
+
+template <class charT>
+void
+test_narrow (charT*, const char *cname)
+{
+    rw_info (0, 0, __LINE__, "UserCtype<%s>::narrow"
+             "(char_type, char) const", cname);
+
+    rw_warn (0, 0, __LINE__, "UserCtype<%s>::narrow"
+             "(char_type, char) const not exercised", cname);
+
+    rw_info (0, 0, __LINE__, "UserCtype<%s>::narrow"
+             "(const char_type*, const char_type*, char, char*) const",
+             cname);
+
+    rw_warn (0, 0, __LINE__, "UserCtype<%s>::narrow"
+             "(const char_type*, const char_type*, char, char*) const"
+             " not exercised",
+             cname);
+}
+
+/***********************************************************************/
+
+/* extern */ int opt_is;
+/* extern */ int opt_scan_is;
+/* extern */ int opt_scan_not;
+
+/* extern */ int opt_toupper;
+/* extern */ int opt_tolower;
+
+/* extern */ int opt_widen;
+/* extern */ int opt_narrow;
+
+
+template <class charT>
+void
+test (charT*, const char *cname)
+{
+#define TEST(func)                                      \
+    if (0 <= opt_ ## func)                              \
+        test_ ## func ((charT*)0, cname);               \
+    else                                                \
+        rw_note (0, 0, __LINE__,                        \
+                 "UserCtype<%s>::%s() tests disabled",  \
+                 cname, # func)
+
+    TEST (is);
+    TEST (scan_is);
+    TEST (scan_not);
+
+    TEST (toupper);
+    TEST (tolower);
+
+    TEST (widen);
+    TEST (narrow);
+}
+
+/***********************************************************************/
+
+static int
+run_test (int, char**)
+{
+    test ((char*)0, "char");
+
+#ifndef _RWSTD_NO_WCHAR_T
+    test ((wchar_t*)0, "wchar_t");
+#endif   // _RWSTD_NO_WCHAR_T
+
+    test ((UserChar*)0, "UserChar");
+
+    return 0;
+}
+
+/***********************************************************************/
+
+int main (int argc, char *argv[])
+{
+    return rw_test (argc, argv, __FILE__,
+                    "",
+                    0,
+                    run_test,
+                    "|-is~ "
+                    "|-scan_is~ "
+                    "|-scan_not~ "
+                    "|-toupper~ "
+                    "|-tolower~ "
+                    "|-widen~ "
+                    "|-narrow~ ",
+                    &opt_is,
+                    &opt_scan_is,
+                    &opt_scan_not,
+                    &opt_toupper,
+                    &opt_tolower,
+                    &opt_widen,
+                    &opt_narrow,
+                    (void*)0 /* sentinel */);
+}

Propchange: incubator/stdcxx/trunk/tests/self/0.ctype.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/tests/self/0.ctype.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/stdcxx/trunk/tests/src/ctype.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/src/ctype.cpp?rev=420234&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/src/ctype.cpp (added)
+++ incubator/stdcxx/trunk/tests/src/ctype.cpp Sat Jul  8 17:47:25 2006
@@ -0,0 +1,1652 @@
+/**************************************************************************
+ *
+ * ctype.cpp - definitions of UserCtype facet members
+ *
+ * $Id$
+ *
+ ***************************************************************************
+ *
+ * Copyright 2006 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Licensed 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.
+ * 
+ **************************************************************************/
+
+// expand _TEST_EXPORT macros
+#define _RWSTD_TEST_SRC
+#include <rw_ctype.h>
+
+#include <stdarg.h>   // for va_arg(), va_list
+#include <string.h>   // for memset()
+
+/**************************************************************************/
+
+typedef unsigned char UChar;
+
+
+_TEST_EXPORT int
+rw_vasnprintf (char**, size_t*, const char*, va_list);
+
+
+static void
+_rw_throw (const char *file, int line, const char *fmt, ...)
+{
+    struct Exception: UserCtypeBase::Exception {
+        char what_ [256];
+
+        /* virtual */ const char* what () const {
+            return what_;
+        }
+    };
+
+    Exception ex;
+
+    va_list va;
+    va_start (va, fmt);
+
+    char *buf = ex.what_;
+    size_t bufsize = sizeof ex.what_;
+    rw_vasnprintf (&buf, &bufsize, fmt, va);
+
+    va_end (va);
+
+    throw ex;
+}
+
+/**************************************************************************/
+
+static const char* const
+_rw_func_names[] = {
+    "is(mask, char_type)",
+    "is(const char_type*, const char_type*, mask*)",
+    "scan_is(mask, const char_type*, const char_type*)",
+    "scan_not(mask, const char_type*, const char_type*)",
+    "to_upper(char_type)",
+    "to_upper(char_type*, const char_type*)",
+    "to_lower(char_type)",
+    "to_lower(char_type*, const char_type*)",
+    "widen(char)",
+    "widen(const char*, const char*, char_type*)",
+    "narrow(char_type, char)",
+    "narrow(const char_type*, const char_type*, char, char*)"
+};
+
+/**************************************************************************/
+
+UserCtypeBase::Exception::
+~Exception ()
+{
+    // no-op
+}
+
+/**************************************************************************/
+
+static const int
+_rw_char_masks [256] = {
+
+#define ALPHA     std::ctype_base::alpha
+#define ALNUM     std::ctype_base::alnum
+#define CNTRL     std::ctype_base::cntrl
+#define DIGIT     std::ctype_base::digit
+#define GRAPH     std::ctype_base::graph
+#define LOWER     std::ctype_base::lower
+#define PRINT     std::ctype_base::print
+#define PUNCT     std::ctype_base::punct
+#define SPACE     std::ctype_base::space
+#define UPPER     std::ctype_base::upper
+#define XDIGIT    std::ctype_base::xdigit
+
+
+#undef  LETTER
+#define LETTER(m) (PRINT | ALPHA | GRAPH | m)
+
+#if 'A' == 0x41   // ASCII
+
+    /* 0x00 NUL */ CNTRL,
+    /* 0x01 SOH */ CNTRL,
+    /* 0x02 STX */ CNTRL,
+    /* 0x03 ETX */ CNTRL,
+    /* 0x04 EOT */ CNTRL,
+    /* 0x05 ENQ */ CNTRL,
+    /* 0x06 ACK */ CNTRL,
+    /* '\a' BEL */ CNTRL,
+    /* 0x08 BS  */ CNTRL,
+    /* '\t' TAB */ SPACE | CNTRL,
+    /* '\n' LF  */ SPACE | CNTRL,
+    /* 0x0b VT  */ SPACE | CNTRL,
+    /* '\f' FF  */ SPACE | CNTRL,
+    /* '\r' CR  */ SPACE | CNTRL,
+    /* 0x0e SO  */ CNTRL,
+    /* 0x0f SI  */ CNTRL,
+    /* 0x10 DLE */ CNTRL,
+    /* 0x11 DC1 */ CNTRL,
+    /* 0x12 DC2 */ CNTRL,
+    /* 0x13 DC3 */ CNTRL,
+    /* 0x14 DC4 */ CNTRL,
+    /* 0x15 NAK */ CNTRL,
+    /* 0x16 SYN */ CNTRL,
+    /* 0x17 ETB */ CNTRL,
+    /* 0x18 CAN */ CNTRL,
+    /* 0x19 EM  */ CNTRL,
+    /* 0x1a SUB */ CNTRL,
+    /* 0x1b ESC */ CNTRL,
+    /* 0x1c FS  */ CNTRL,
+    /* 0x1d GS  */ CNTRL,
+    /* 0x1e RS  */ CNTRL,
+    /* 0x1f US  */ CNTRL,
+    /* ' '      */ SPACE | PRINT,
+    /* '!'      */ PRINT | PUNCT | GRAPH,
+    /* '"'      */ PRINT | PUNCT | GRAPH,
+    /* '#'      */ PRINT | PUNCT | GRAPH,
+    /* '$'      */ PRINT | PUNCT | GRAPH,
+    /* '%'      */ PRINT | PUNCT | GRAPH,
+    /* '&'      */ PRINT | PUNCT | GRAPH,
+    /* '\''     */ PRINT | PUNCT | GRAPH,
+    /* '('      */ PRINT | PUNCT | GRAPH,
+    /* ')'      */ PRINT | PUNCT | GRAPH,
+    /* '*'      */ PRINT | PUNCT | GRAPH,
+    /* '+'      */ PRINT | PUNCT | GRAPH,
+    /* ','      */ PRINT | PUNCT | GRAPH,
+    /* '-'      */ PRINT | PUNCT | GRAPH,
+    /* '.'      */ PRINT | PUNCT | GRAPH,
+    /* '/'      */ PRINT | PUNCT | GRAPH,
+    /* '0'      */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /* '1'      */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /* '2'      */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /* '3'      */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /* '4'      */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /* '5'      */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /* '6'      */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /* '7'      */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /* '8'      */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /* '9'      */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /* ':'      */ PRINT | PUNCT | GRAPH,
+    /* ';'      */ PRINT | PUNCT | GRAPH,
+    /* '<'      */ PRINT | PUNCT | GRAPH,
+    /* '='      */ PRINT | PUNCT | GRAPH,
+    /* '>'      */ PRINT | PUNCT | GRAPH,
+    /* '?'      */ PRINT | PUNCT | GRAPH,
+    /* '@'      */ PRINT | PUNCT | GRAPH,
+
+    /* 'A'      */ LETTER (UPPER | XDIGIT),
+    /* 'B'      */ LETTER (UPPER | XDIGIT),
+    /* 'C'      */ LETTER (UPPER | XDIGIT),
+    /* 'D'      */ LETTER (UPPER | XDIGIT),
+    /* 'E'      */ LETTER (UPPER | XDIGIT),
+    /* 'F'      */ LETTER (UPPER | XDIGIT),
+    /* 'G'      */ LETTER (UPPER),
+    /* 'H'      */ LETTER (UPPER),
+    /* 'I'      */ LETTER (UPPER),
+    /* 'J'      */ LETTER (UPPER),
+    /* 'K'      */ LETTER (UPPER),
+    /* 'L'      */ LETTER (UPPER),
+    /* 'M'      */ LETTER (UPPER),
+    /* 'N'      */ LETTER (UPPER),
+    /* 'O'      */ LETTER (UPPER),
+    /* 'P'      */ LETTER (UPPER),
+    /* 'Q'      */ LETTER (UPPER),
+    /* 'R'      */ LETTER (UPPER),
+    /* 'S'      */ LETTER (UPPER),
+    /* 'T'      */ LETTER (UPPER),
+    /* 'U'      */ LETTER (UPPER),
+    /* 'V'      */ LETTER (UPPER),
+    /* 'W'      */ LETTER (UPPER),
+    /* 'X'      */ LETTER (UPPER),
+    /* 'Y'      */ LETTER (UPPER),
+    /* 'Z'      */ LETTER (UPPER),
+
+    /* '['      */ PRINT | PUNCT | GRAPH,
+    /* '\\'     */ PRINT | PUNCT | GRAPH,
+    /* ']'      */ PRINT | PUNCT | GRAPH,
+    /* '^'      */ PRINT | PUNCT | GRAPH,
+    /* '_'      */ PRINT | PUNCT | GRAPH,
+    /* '`'      */ PRINT | PUNCT | GRAPH,
+
+    /* 'a'      */ LETTER (LOWER | XDIGIT),     
+    /* 'b'      */ LETTER (LOWER | XDIGIT),     
+    /* 'c'      */ LETTER (LOWER | XDIGIT),     
+    /* 'd'      */ LETTER (LOWER | XDIGIT),     
+    /* 'e'      */ LETTER (LOWER | XDIGIT),     
+    /* 'f'      */ LETTER (LOWER | XDIGIT),     
+    /* 'g'      */ LETTER (LOWER),              
+    /* 'h'      */ LETTER (LOWER),              
+    /* 'i'      */ LETTER (LOWER),              
+    /* 'j'      */ LETTER (LOWER),              
+    /* 'k'      */ LETTER (LOWER),              
+    /* 'l'      */ LETTER (LOWER),              
+    /* 'm'      */ LETTER (LOWER),              
+    /* 'n'      */ LETTER (LOWER),              
+    /* 'o'      */ LETTER (LOWER),              
+    /* 'p'      */ LETTER (LOWER),              
+    /* 'q'      */ LETTER (LOWER),              
+    /* 'r'      */ LETTER (LOWER),              
+    /* 's'      */ LETTER (LOWER),              
+    /* 't'      */ LETTER (LOWER),              
+    /* 'u'      */ LETTER (LOWER),              
+    /* 'v'      */ LETTER (LOWER),              
+    /* 'w'      */ LETTER (LOWER),              
+    /* 'x'      */ LETTER (LOWER),              
+    /* 'y'      */ LETTER (LOWER),              
+    /* 'z'      */ LETTER (LOWER),
+
+    /* '{'      */ PRINT | PUNCT | GRAPH,
+    /* '|'      */ PRINT | PUNCT | GRAPH,
+    /* '}'      */ PRINT | PUNCT | GRAPH,
+    /* '~'      */ PRINT | PUNCT | GRAPH,
+    /* 0x7f DEL */ CNTRL
+
+#elif 'A' == 0xc1   // EBCDIC
+
+    /* NUL */ CNTRL,
+    /* SOH */ CNTRL,
+    /* STX */ CNTRL,
+    /* ETX */ CNTRL,
+    /* PF  */ CNTRL,
+    /* HT  */ CNTRL,
+    /* LC  */ CNTRL,
+    /* DEL */ CNTRL,
+    /*     */ 0,
+    /*     */ 0,
+    /* SMM */ CNTRL,
+    /* VT  */ SPACE | CNTRL,
+    /* FF  */ SPACE | CNTRL,
+    /* CR  */ SPACE | CNTRL,
+    /* SO  */ CNTRL,
+    /* SI  */ CNTRL,
+    /* DLE */ CNTRL,
+    /* DC1 */ CNTRL,
+    /* DC2 */ CNTRL,
+    /* TM  */ CNTRL,
+    /* RES */ CNTRL,
+    /* NL  */ CNTRL,
+    /* BS  */ CNTRL,
+    /* IL  */ CNTRL,
+    /* CAN */ CNTRL,
+    /* EM  */ CNTRL,
+    /* CC  */ CNTRL,
+    /* CU1 */ CNTRL,
+    /* IFS */ CNTRL,
+    /* IGS */ CNTRL,
+    /* IRS */ CNTRL,
+    /* IUS */ CNTRL,
+    /* DS  */ CNTRL,
+    /* SOS */ CNTRL,
+    /* FS  */ CNTRL,
+    /*     */ 0,
+    /* BYP */ CNTRL,
+    /* LF  */ SPACE | CNTRL,
+    /* ETB */ CNTRL,
+    /* ESC */ CNTRL,
+    /*     */ 0,
+    /*     */ 0,
+    /* SM  */ CNTRL,
+    /* CU2 */ CNTRL,
+    /*     */ 0,
+    /* ENQ */ CNTRL,
+    /* ACK */ CNTRL,
+    /* BEL */ CNTRL,
+    /*     */ 0,
+    /*     */ 0,
+    /* SYN */ CNTRL,
+    /*     */ 0,
+    /* PN  */ CNTRL,
+    /* RS  */ CNTRL,
+    /* UC  */ CNTRL,
+    /* EOT */ CNTRL,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /* CU3 */ CNTRL,
+    /* DC4 */ CNTRL,
+    /* NAK */ CNTRL,
+    /*     */ 0,
+    /* SUB */ CNTRL,
+    /* ' ' */ SPACE | PRINT,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /* ct. */ PRINT | PUNCT | GRAPH,
+    /* '.' */ PRINT | PUNCT | GRAPH,
+    /* '<' */ PRINT | PUNCT | GRAPH,
+    /* '(' */ PRINT | PUNCT | GRAPH,
+    /* '+' */ PRINT | PUNCT | GRAPH,
+    /* '|' */ PRINT | PUNCT | GRAPH,
+    /* '&' */ PRINT | PUNCT | GRAPH,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /* '!' */ PRINT | PUNCT | GRAPH,
+    /* '$' */ PRINT | PUNCT | GRAPH,
+    /* '*' */ PRINT | PUNCT | GRAPH,
+    /* ')' */ PRINT | PUNCT | GRAPH,
+    /* ';' */ PRINT | PUNCT | GRAPH,
+    /* '~' */ PRINT | PUNCT | GRAPH,
+    /* '-' */ PRINT | PUNCT | GRAPH,
+    /* '/' */ PRINT | PUNCT | GRAPH,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /* ',' */ PRINT | PUNCT | GRAPH,
+    /* '%' */ PRINT | PUNCT | GRAPH,
+    /* '_' */ PRINT | PUNCT | GRAPH,
+    /* '>' */ PRINT | PUNCT | GRAPH,
+    /* '?' */ PRINT | PUNCT | GRAPH,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /* ':' */ PRINT | PUNCT | GRAPH,
+    /* '#' */ PRINT | PUNCT | GRAPH,
+    /* '@' */ PRINT | PUNCT | GRAPH,
+    /* ''' */ PRINT | PUNCT | GRAPH,
+    /* '=' */ PRINT | PUNCT | GRAPH,
+    /* '"' */ PRINT | PUNCT | GRAPH,
+    /*     */ 0,
+    /* 'a' */ LETTER (LOWER | XDIGIT),
+    /* 'b' */ LETTER (LOWER | XDIGIT),
+    /* 'c' */ LETTER (LOWER | XDIGIT),
+    /* 'd' */ LETTER (LOWER | XDIGIT),
+    /* 'e' */ LETTER (LOWER | XDIGIT),
+    /* 'f' */ LETTER (LOWER | XDIGIT),
+    /* 'g' */ LETTER (LOWER),
+    /* 'h' */ LETTER (LOWER),
+    /* 'i' */ LETTER (LOWER),
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /* 'j' */ LETTER (LOWER),
+    /* 'k' */ LETTER (LOWER),
+    /* 'l' */ LETTER (LOWER),
+    /* 'm' */ LETTER (LOWER),
+    /* 'n' */ LETTER (LOWER),
+    /* 'o' */ LETTER (LOWER),
+    /* 'p' */ LETTER (LOWER),
+    /* 'q' */ LETTER (LOWER),
+    /* 'r' */ LETTER (LOWER),
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /* 's' */ LETTER (LOWER),
+    /* 't' */ LETTER (LOWER),
+    /* 'u' */ LETTER (LOWER),
+    /* 'v' */ LETTER (LOWER),
+    /* 'w' */ LETTER (LOWER),
+    /* 'x' */ LETTER (LOWER),
+    /* 'y' */ LETTER (LOWER),
+    /* 'z' */ LETTER (LOWER),
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /* '`' */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /* 'A' */ LETTER (UPPER | XDIGIT),
+    /* 'B' */ LETTER (UPPER | XDIGIT),
+    /* 'C' */ LETTER (UPPER | XDIGIT),
+    /* 'D' */ LETTER (UPPER | XDIGIT),
+    /* 'E' */ LETTER (UPPER | XDIGIT),
+    /* 'F' */ LETTER (UPPER | XDIGIT),
+    /* 'G' */ LETTER (UPPER),
+    /* 'H' */ LETTER (UPPER),
+    /* 'I' */ LETTER (UPPER),
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /* 'J' */ LETTER (UPPER),
+    /* 'K' */ LETTER (UPPER),
+    /* 'L' */ LETTER (UPPER),
+    /* 'M' */ LETTER (UPPER),
+    /* 'N' */ LETTER (UPPER),
+    /* 'O' */ LETTER (UPPER),
+    /* 'P' */ LETTER (UPPER),
+    /* 'Q' */ LETTER (UPPER),
+    /* 'R' */ LETTER (UPPER),
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /* 'S' */ LETTER (UPPER),
+    /* 'T' */ LETTER (UPPER),
+    /* 'U' */ LETTER (UPPER),
+    /* 'V' */ LETTER (UPPER),
+    /* 'W' */ LETTER (UPPER),
+    /* 'X' */ LETTER (UPPER),
+    /* 'Y' */ LETTER (UPPER),
+    /* 'Z' */ LETTER (UPPER),
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /* '0' */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /* '1' */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /* '2' */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /* '3' */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /* '4' */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /* '5' */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /* '6' */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /* '7' */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /* '8' */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /* '9' */ PRINT | DIGIT | GRAPH | XDIGIT,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0,
+    /*     */ 0
+
+#else   // 'A' != 0x41 && 'A' != 0xc1
+#  error unknown character set (neither ASCII nor EBCDIC)
+#endif   // ASCII or EBCDIC
+
+};
+
+
+UserCtypeBase::
+UserCtypeBase (const char *cname)
+    : cname_ (cname), masks_ (_rw_char_masks), chars_ (0),
+      upper_ (0), lower_ (0), narrow_ (0), wide_ (0),
+      n_all_calls_ (0),
+      throw_char_ (-1), throw_on_invalid_ (false)
+{
+    memset (n_calls_, 0, sizeof n_calls_);
+    memset (n_throws_, 0, sizeof n_throws_);
+    memset (throw_at_calls_, 0, sizeof throw_at_calls_);
+}
+
+/**************************************************************************/
+
+// records a call to the object's member function fun and
+// throws an exception if the number of calls to the member
+// function reaches the limit specified by throw_at_calls_
+static void
+_rw_funcall (const UserCtypeBase    &ctp,
+             UserCtypeBase::MemFunc  mf)
+{
+    UserCtypeBase* const pctp = _RWSTD_CONST_CAST (UserCtypeBase*, &ctp);
+
+    // increment the number of calls regardless of success
+    ++pctp->n_all_calls_;
+    ++pctp->n_calls_ [mf];
+
+    // check the number of calls and throw an exception
+    // if the specified limit has been reached
+    if (ctp.n_calls_ [mf] == ctp.throw_at_calls_ [mf]) {
+        // increment the exception counter for this function
+        ++pctp->n_throws_ [mf];
+
+        _rw_throw (__FILE__, __LINE__,
+                   "UserCtype<%s>::%s: reached call limit of %zu",
+                   ctp.cname_, _rw_func_names [mf], ctp.throw_at_calls_);
+
+        RW_ASSERT (!"logic error: should not reach");
+    }
+}
+
+/**************************************************************************/
+
+static void
+_rw_check_char (const UserCtypeBase   &ctp,
+                UserCtypeBase::MemFunc mf,
+                size_t                 uch)
+{
+    if (0 <= ctp.throw_char_ && size_t (ctp.throw_char_) == uch) {
+
+        UserCtypeBase* const pctp = _RWSTD_CONST_CAST (UserCtypeBase*, &ctp);
+        ++pctp->n_throws_ [mf];
+
+        _rw_throw (__FILE__, __LINE__,
+                   "UserCtype<%s>::%s: invalid character: %{#lc}",
+                   ctp.cname_, _rw_func_names [mf], int (uch));
+
+        RW_ASSERT (!"logic error: should not reach");
+    }
+}
+
+/**************************************************************************/
+
+static UserCtype<char>::mask*
+_rw_make_mask_vec (const int *chars, const int *masks)
+{
+    if (0 == chars) {
+        RW_ASSERT (0 == masks);
+        return 0;
+    }
+
+    RW_ASSERT (0 != masks);
+
+    typedef UserCtype<char>::mask Mask;
+
+    const size_t size = UserCtype<char>::table_size;
+    Mask* const  vec  = new Mask [size];
+
+    memset (vec, 0, size * sizeof *vec);
+
+    for (size_t i = 0; 0 <= chars [i]; ++i)
+        vec [UChar (chars [i])] = Mask (masks [i]);
+
+    return vec;
+}
+
+
+UserCtype<char>::
+UserCtype (const int *chars, const int *masks, size_t refs)
+    : Base (_rw_make_mask_vec (chars, masks), true, refs),
+      UserCtypeBase ("char")
+{
+    chars_ = chars;
+    masks_ = masks;
+}
+
+
+UserCtype<char>::char_type
+UserCtype<char>::
+do_toupper (char_type ch) const
+{
+    _rw_funcall (*this, mf_toupper);
+
+    const UChar uch = UChar (ch);
+
+    _rw_check_char (*this, mf_toupper, uch);
+
+    if (0 == upper_) {
+        if (masks_ [uch] & LOWER) {
+#if 'A' == 0x41   // ASCII
+            return char_type (uch - 32);
+#else   // EBCDIC
+            return char_type (uch + 64);
+#endif
+        }
+    }
+    else {
+        // FIXME: implement this
+        RW_ASSERT (!"do_toupper() not implemented");
+    }
+
+    return ch;
+}
+
+
+const UserCtype<char>::char_type*
+UserCtype<char>::
+do_toupper (char_type *lo, const char_type *hi) const
+{
+    _rw_funcall (*this, mf_toupper_range);
+
+    if (0 == upper_) {
+        for ( ; lo < hi; ++lo) {
+
+            const UChar uch = UChar (*lo);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            if (masks_ [uch] & LOWER) {
+#if 'A' == 0x41   // ASCII
+                *lo = char_type (uch - 32);
+#else   // EBCDIC
+                *lo = char_type (uch + 64);
+#endif
+            }
+        }
+    }
+    else {
+        // FIXME: implement this 
+        RW_ASSERT (!"do_toupper() not implemented");
+    }
+
+    return lo;
+}
+
+
+UserCtype<char>::char_type
+UserCtype<char>::
+do_tolower (char_type ch) const
+{
+    _rw_funcall (*this, mf_tolower);
+
+    _rw_check_char (*this, mf_toupper, UChar (ch));
+
+    if (0 == chars_) {
+        if (masks_ [UChar (ch)] & UPPER) {
+#if 'A' == 0x41   // ASCII
+            return char_type (UChar (ch + 32));
+#else   // EBCDIC
+            return char_type (UChar (ch - 64));
+#endif
+        }
+    }
+    else {
+        // FIXME: implement this
+        RW_ASSERT (!"do_toupper() not implemented");
+    }
+
+    return ch;
+}
+
+
+const UserCtype<char>::char_type*
+UserCtype<char>::
+do_tolower (char_type *lo, const char_type *hi) const
+{
+    _rw_funcall (*this, mf_tolower_range);
+
+    if (0 == chars_) {
+        for ( ; lo < hi; ++lo) {
+
+            const UChar uch = UChar (*lo);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            if (masks_ [uch] & UPPER) {
+#if 'A' == 0x41   // ASCII
+                *lo = char_type (uch - 32);
+#else   // EBCDIC
+                *lo = char_type (uch + 64);
+#endif
+            }
+        }
+    }
+    else {
+        // FIXME: implement this 
+        RW_ASSERT (!"do_toupper() not implemented");
+    }
+
+    return lo;
+}
+
+
+UserCtype<char>::char_type
+UserCtype<char>::
+do_widen (char ch) const
+{
+    _rw_funcall (*this, mf_widen);
+
+    const UChar uch = UChar (ch);
+
+    _rw_check_char (*this, mf_toupper, uch);
+
+    if (narrow_ && wide_) {
+        for (size_t i = 0; 0 <= narrow_ [i]; ++i) {
+            if (uch == UChar (narrow_ [i])) {
+                if (0 <= wide_ [i])
+                    return UChar (wide_ [i]);
+
+                if (throw_on_invalid_)
+                    throw;
+
+                break;
+            }
+        }
+    }
+
+    return ch;
+}
+
+
+const char*
+UserCtype<char>::
+do_widen (const char *lo, const char *hi, char_type *dst) const
+{
+    _rw_funcall (*this, mf_widen_range);
+
+    if (narrow_ && wide_) {
+        for ( ; lo < hi; ++lo, ++dst) {
+
+            const UChar uch = *lo;
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            for (size_t i = 0; 0 <= narrow_ [i]; ++i) {
+                if (uch == UChar (narrow_ [i])) {
+                    if (0 <= wide_ [i])
+                        *dst = UChar (wide_ [i]);
+
+                    if (throw_on_invalid_)
+                        throw;
+
+                    break;
+                }
+            }
+        }
+    }
+    else if (throw_char_ < 0 || int (_RWSTD_UCHAR_MAX) < throw_char_) {
+        const size_t nelems = size_t (hi - lo);
+        memcpy (dst, lo, nelems);
+        lo += nelems;
+    }
+    else {
+        for (; lo < hi; ++lo, ++dst) {
+
+            const UChar uch = UChar (*lo);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            *dst = char_type (uch);
+        }
+    }
+
+    return lo;
+}
+
+
+char UserCtype<char>::
+do_narrow (char_type ch, char dfault) const
+{
+    _rw_funcall (*this, mf_narrow);
+
+    const UChar uch = UChar (ch);
+
+    _rw_check_char (*this, mf_toupper, uch);
+
+    if (narrow_ && wide_) {
+        for (size_t i = 0; 0 <= wide_ [i]; ++i) {
+            if (uch == UChar (wide_ [i])) {
+                if (0 <= wide_ [i])
+                    return UChar (wide_ [i]);
+
+                if (throw_on_invalid_)
+                    throw;
+
+                break;
+            }
+        }
+    }
+
+    return dfault;
+}
+
+
+const UserCtype<char>::char_type*
+UserCtype<char>::
+do_narrow (const char_type *lo, const char_type *hi, char dflt, char *dst) const
+{
+    _rw_funcall (*this, mf_narrow_range);
+
+    if (narrow_ && wide_) {
+        for ( ; lo < hi; ++lo, ++dst) {
+
+            const UChar uch = UChar (*lo);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            for (size_t i = 0; 0 <= wide_ [i]; ++i) {
+                if (uch == UChar (wide_ [i])) {
+                    *dst = 0 <= narrow_ [i] ? UChar (wide_ [i]) : UChar (dflt);
+                    break;
+                }
+            }
+        }
+    }
+    else if (throw_char_ < 0 || int (_RWSTD_UCHAR_MAX) < throw_char_) {
+        const size_t nelems = size_t (hi - lo);
+        memcpy (dst, lo, nelems);
+        lo += nelems;
+    }
+    else {
+        for (; lo < hi; ++lo, ++dst) {
+
+            const UChar uch = UChar (*lo);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            *dst = char_type (uch);
+        }
+    }
+
+    return lo;
+}
+
+/**************************************************************************/
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+UserCtype<wchar_t>::
+UserCtype (const int *chars, const int *masks, size_t refs)
+    : Base (refs), UserCtypeBase ("wchar_t")
+{
+    if (0 == masks) {
+        // when masks is null so must chars
+        RW_ASSERT (0 == chars);
+        masks = _rw_char_masks;
+    }
+
+    chars_ = chars;
+    masks_ = masks;
+}
+
+
+bool UserCtype<wchar_t>::
+do_is (mask m, char_type ch) const
+{
+    _rw_funcall (*this, mf_is);
+
+    const size_t uch = size_t (ch);
+
+    _rw_check_char (*this, mf_toupper, uch);
+
+    if (masks_ == _rw_char_masks) {
+        return uch < 256 ? 0 != (masks_ [uch] & m) : false;
+    }
+
+    for (size_t i = 0; 0 <= chars_ [i]; ++i)
+        if (chars_ [i] == int (ch))
+            return 0 != (masks_ [i] & m);
+
+    return false;
+}
+
+
+const UserCtype<wchar_t>::char_type*
+UserCtype<wchar_t>::
+do_is (const char_type *lo, const char_type *hi, mask *vec) const
+{
+    _rw_funcall (*this, mf_is_range);
+
+    if (masks_ == _rw_char_masks) {
+        for ( ; lo < hi; ++lo, ++vec) {
+
+            const size_t uch = size_t (*lo);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            *vec = mask (uch < 256 ? masks_ [uch] : 0);
+        }
+    }
+    else {
+        for ( ; lo < hi; ++lo, ++vec) {
+
+            _rw_check_char (*this, mf_toupper, size_t (*lo));
+
+            bool found = false;
+
+            for (size_t i = 0; 0 <= chars_ [i]; ++i) {
+                if (chars_ [i] == int (*lo)) {
+                    *vec  = mask (masks_ [i]);
+                    found = true;
+                    break;
+                }
+            }
+
+            if (!found && throw_on_invalid_)
+                throw;
+        }
+    }
+
+    return lo;
+}
+
+
+const UserCtype<wchar_t>::char_type*
+UserCtype<wchar_t>::
+do_scan_is (mask m, const char_type *lo, const char_type *hi) const
+{
+    _rw_funcall (*this, mf_scan_is);
+
+    if (masks_ == _rw_char_masks) {
+        for ( ; lo < hi; ++lo) {
+            const size_t uch = size_t (*lo);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            if (uch < 256 && masks_ [uch] & m)
+                break;
+        }
+    }
+    else {
+        for ( ; lo < hi; ++lo) {
+
+            _rw_check_char (*this, mf_toupper, size_t (*lo));
+
+            for (size_t i = 0; 0 <= chars_ [i]; ++i) {
+                if (chars_ [i] == int (*lo) && masks_ [i] & m)
+                    return lo;
+            }
+        }
+    }
+
+    return lo;
+}
+
+
+const UserCtype<wchar_t>::char_type*
+UserCtype<wchar_t>::
+do_scan_not (mask m, const char_type *lo, const char_type *hi) const
+{
+    _rw_funcall (*this, mf_scan_not);
+
+    if (masks_ == _rw_char_masks) {
+        for ( ; lo < hi; ++lo) {
+
+            const size_t uch = size_t (*lo);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            if (uch < 256 && 0 == (masks_ [uch] & m))
+                break;
+        }
+    }
+    else {
+        for ( ; lo < hi; ++lo) {
+
+            _rw_check_char (*this, mf_toupper, size_t (*lo));
+
+            for (size_t i = 0; 0 <= chars_ [i]; ++i) {
+                if (chars_ [i] == int (*lo) && 0 == (masks_ [i] & m))
+                    return lo;
+            }
+        }
+    }
+
+    return lo;
+}
+
+
+UserCtype<wchar_t>::char_type
+UserCtype<wchar_t>::
+do_toupper (char_type ch) const
+{
+    _rw_funcall (*this, mf_toupper);
+
+    const size_t uch = size_t (ch);
+
+    _rw_check_char (*this, mf_toupper, uch);
+
+    if (0 == upper_) {
+
+        if (uch < 256 && masks_ [uch] & LOWER) {
+#if 'A' == 0x41   // ASCII
+            return char_type (uch - 32);
+#else   // EBCDIC
+            return char_type (uch + 64);
+#endif
+        }
+    }
+    else {
+        // FIXME: implement this
+        RW_ASSERT (!"do_toupper() not implemented");
+    }
+
+    return ch;
+}
+
+
+const UserCtype<wchar_t>::char_type*
+UserCtype<wchar_t>::
+do_toupper (char_type *lo, const char_type *hi) const
+{
+    _rw_funcall (*this, mf_toupper_range);
+
+    if (0 == upper_) {
+        for ( ; lo < hi; ++lo) {
+            const size_t uch = size_t (*lo);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            if (uch < 256 && masks_ [uch] & LOWER) {
+#if 'A' == 0x41   // ASCII
+                *lo = char_type (uch - 32);
+#else   // EBCDIC
+                *lo = char_type (uch + 64);
+#endif
+            }
+        }
+    }
+    else {
+        // FIXME: implement this 
+        RW_ASSERT (!"do_toupper() not implemented");
+    }
+
+    return lo;
+}
+
+
+UserCtype<wchar_t>::char_type
+UserCtype<wchar_t>::
+do_tolower (char_type ch) const
+{
+    _rw_funcall (*this, mf_tolower);
+
+    const size_t uch = size_t (ch);
+
+    _rw_check_char (*this, mf_toupper, uch);
+
+    if (masks_ == _rw_char_masks) {
+        if (uch < 256 && masks_ [uch] & UPPER) {
+#if 'A' == 0x41   // ASCII
+            return char_type (uch + 32);
+#else   // EBCDIC
+            return char_type (uch - 64);
+#endif
+        }
+    }
+    else {
+        // FIXME: implement this
+        RW_ASSERT (!"do_toupper() not implemented");
+    }
+
+    return ch;
+}
+
+
+const UserCtype<wchar_t>::char_type*
+UserCtype<wchar_t>::
+do_tolower (char_type *lo, const char_type *hi) const
+{
+    _rw_funcall (*this, mf_tolower_range);
+
+    if (masks_ == _rw_char_masks) {
+        for ( ; lo < hi; ++lo) {
+
+            const size_t uch = size_t (*lo);
+
+            if (uch < 256 && masks_ [uch] & UPPER) {
+#if 'A' == 0x41   // ASCII
+                *lo = char_type (uch - 32);
+#else   // EBCDIC
+                *lo = char_type (uch + 64);
+#endif
+            }
+        }
+    }
+    else {
+        // FIXME: implement this 
+        RW_ASSERT (!"do_toupper() not implemented");
+    }
+
+    return lo;
+}
+
+
+UserCtype<wchar_t>::char_type
+UserCtype<wchar_t>::
+do_widen (char ch) const
+{
+    _rw_funcall (*this, mf_widen);
+
+    const UChar uch = UChar (ch);
+
+    _rw_check_char (*this, mf_toupper, uch);
+
+    if (narrow_ && wide_) {
+        for (size_t i = 0; 0 <= narrow_ [i]; ++i) {
+            if (int (uch) == narrow_ [i]) {
+                if (0 <= wide_ [i])
+                    return char_type (wide_ [i]);
+
+                if (throw_on_invalid_)
+                    throw;
+
+                break;
+            }
+        }
+    }
+
+    return ch;
+}
+
+
+const char*
+UserCtype<wchar_t>::
+do_widen (const char *lo, const char *hi, char_type *dst) const
+{
+    _rw_funcall (*this, mf_widen_range);
+
+    if (narrow_ && wide_) {
+        for ( ; lo < hi; ++lo, ++dst) {
+
+            const size_t uch = size_t (*lo);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            for (size_t i = 0; 0 <= narrow_ [i]; ++i) {
+                if (int (uch) == narrow_ [i]) {
+                    if (0 <= wide_ [i])
+                        *dst = char_type (wide_ [i]);
+
+                    if (throw_on_invalid_)
+                        throw;
+
+                    break;
+                }
+            }
+        }
+    }
+    else {
+        for (; lo < hi; ++lo, ++dst) {
+
+            const UChar uch = UChar (*lo);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            *dst = char_type (uch);
+        }
+    }
+
+    return lo;
+}
+
+
+char UserCtype<wchar_t>::
+do_narrow (char_type ch, char dfault) const
+{
+    _rw_funcall (*this, mf_narrow);
+
+    const size_t uch = size_t (ch);
+
+    _rw_check_char (*this, mf_toupper, uch);
+
+    if (narrow_ && wide_) {
+        for (size_t i = 0; 0 <= wide_ [i]; ++i) {
+            if (int (uch) == wide_ [i]) {
+                if (0 <= wide_ [i])
+                    return char (wide_ [i]);
+
+                if (throw_on_invalid_)
+                    throw;
+
+                break;
+            }
+        }
+    }
+
+    return dfault;
+}
+
+
+const UserCtype<wchar_t>::char_type*
+UserCtype<wchar_t>::
+do_narrow (const char_type *lo, const char_type *hi, char dflt, char *dst) const
+{
+    _rw_funcall (*this, mf_narrow_range);
+
+    if (narrow_ && wide_) {
+        for ( ; lo < hi; ++lo, ++dst) {
+
+            const size_t uch = size_t (*lo);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            for (size_t i = 0; 0 <= wide_ [i]; ++i) {
+                if (int (uch) == wide_ [i]) {
+                    *dst = 0 <= narrow_ [i] ? char (wide_ [i]) : dflt;
+                    break;
+                }
+            }
+        }
+    }
+    else {
+        for (; lo < hi; ++lo, ++dst) {
+
+            const size_t uch = size_t (*lo);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            *dst = char (uch);
+        }
+    }
+
+    return lo;
+}
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+/**************************************************************************/
+
+UserCtype<UserChar>::
+UserCtype (const int *chars, const int *masks, size_t refs)
+    : Base (refs), UserCtypeBase ("wchar_t")
+{
+    if (0 == masks) {
+        // when masks is null so must chars
+        RW_ASSERT (0 == chars);
+        masks = _rw_char_masks;
+    }
+
+    chars_ = chars;
+    masks_ = masks;
+}
+
+
+bool UserCtype<UserChar>::
+do_is (mask m, char_type ch) const
+{
+    _rw_funcall (*this, mf_is);
+
+    const size_t uch = size_t (ch.c);
+
+    _rw_check_char (*this, mf_toupper, uch);
+
+    if (masks_ == _rw_char_masks) {
+        return uch < 256 ? 0 != (masks_ [uch] & m) : false;
+    }
+
+    for (size_t i = 0; 0 <= chars_ [i]; ++i)
+        if (chars_ [i] == int (uch))
+            return 0 != (masks_ [i] & m);
+
+    return false;
+}
+
+
+const UserCtype<UserChar>::char_type*
+UserCtype<UserChar>::
+do_is (const char_type *lo, const char_type *hi, mask *vec) const
+{
+    _rw_funcall (*this, mf_is_range);
+
+    if (masks_ == _rw_char_masks) {
+        for ( ; lo < hi; ++lo, ++vec) {
+
+            const size_t uch = size_t (lo->c);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            *vec = mask (uch < 256 ? masks_ [uch] : 0);
+        }
+    }
+    else {
+        for ( ; lo < hi; ++lo, ++vec) {
+
+            _rw_check_char (*this, mf_toupper, size_t (lo->c));
+
+            bool found = false;
+
+            for (size_t i = 0; 0 <= chars_ [i]; ++i) {
+                if (chars_ [i] == int (UChar (lo->c))) {
+                    *vec  = mask (masks_ [i]);
+                    found = true;
+                    break;
+                }
+            }
+
+            if (!found && throw_on_invalid_)
+                throw;
+        }
+    }
+
+    return lo;
+}
+
+
+const UserCtype<UserChar>::char_type*
+UserCtype<UserChar>::
+do_scan_is (mask m, const char_type *lo, const char_type *hi) const
+{
+    _rw_funcall (*this, mf_scan_is);
+
+    if (masks_ == _rw_char_masks) {
+        for ( ; lo < hi; ++lo) {
+            const size_t uch = size_t (lo->c);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            if (uch < 256 && masks_ [uch] & m)
+                break;
+        }
+    }
+    else {
+        for ( ; lo < hi; ++lo) {
+
+            _rw_check_char (*this, mf_toupper, size_t (lo->c));
+
+            for (size_t i = 0; 0 <= chars_ [i]; ++i) {
+                if (chars_ [i] == int (UChar (lo->c)) && masks_ [i] & m)
+                    return lo;
+            }
+        }
+    }
+
+    return lo;
+}
+
+
+const UserCtype<UserChar>::char_type*
+UserCtype<UserChar>::
+do_scan_not (mask m, const char_type *lo, const char_type *hi) const
+{
+    _rw_funcall (*this, mf_scan_not);
+
+    if (masks_ == _rw_char_masks) {
+        for ( ; lo < hi; ++lo) {
+
+            const size_t uch = size_t (lo->c);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            if (uch < 256 && 0 == (masks_ [uch] & m))
+                break;
+        }
+    }
+    else {
+        for ( ; lo < hi; ++lo) {
+
+            const size_t uch = size_t (lo->c);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            for (size_t i = 0; 0 <= chars_ [i]; ++i) {
+                if (chars_ [i] == int (uch) && 0 == (masks_ [i] & m))
+                    return lo;
+            }
+        }
+    }
+
+    return lo;
+}
+
+
+UserCtype<UserChar>::char_type
+UserCtype<UserChar>::
+do_toupper (char_type ch) const
+{
+    _rw_funcall (*this, mf_toupper);
+
+    const size_t uch = size_t (ch.c);
+
+    _rw_check_char (*this, mf_toupper, uch);
+
+    if (0 == upper_) {
+
+        if (uch < 256 && masks_ [uch] & LOWER) {
+#if 'A' == 0x41   // ASCII
+            ch.c = UChar (uch - 32);
+#else   // EBCDIC
+            ch.c = UChar (uch + 64);
+#endif
+        }
+    }
+    else {
+        // FIXME: implement this
+        RW_ASSERT (!"do_toupper() not implemented");
+    }
+
+    return ch;
+}
+
+
+const UserCtype<UserChar>::char_type*
+UserCtype<UserChar>::
+do_toupper (char_type *lo, const char_type *hi) const
+{
+    _rw_funcall (*this, mf_toupper_range);
+
+    if (0 == upper_) {
+        for ( ; lo < hi; ++lo) {
+            const size_t uch = size_t (lo->c);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            if (uch < 256 && masks_ [uch] & LOWER) {
+#if 'A' == 0x41   // ASCII
+                lo->c = UChar (uch - 32);
+#else   // EBCDIC
+                lo->c = UChar (uch + 64);
+#endif
+            }
+        }
+    }
+    else {
+        // FIXME: implement this 
+        RW_ASSERT (!"do_toupper() not implemented");
+    }
+
+    return lo;
+}
+
+
+UserCtype<UserChar>::char_type
+UserCtype<UserChar>::
+do_tolower (char_type ch) const
+{
+    _rw_funcall (*this, mf_tolower);
+
+    const size_t uch = size_t (ch.c);
+
+    _rw_check_char (*this, mf_toupper, uch);
+
+    if (masks_ == _rw_char_masks) {
+        if (uch < 256 && masks_ [uch] & UPPER) {
+#if 'A' == 0x41   // ASCII
+            ch.c = UChar (uch + 32);
+#else   // EBCDIC
+            ch.c = UChar (uch - 64);
+#endif
+        }
+    }
+    else {
+        // FIXME: implement this
+        RW_ASSERT (!"do_toupper() not implemented");
+    }
+
+    return ch;
+}
+
+
+const UserCtype<UserChar>::char_type*
+UserCtype<UserChar>::
+do_tolower (char_type *lo, const char_type *hi) const
+{
+    _rw_funcall (*this, mf_tolower_range);
+
+    if (masks_ == _rw_char_masks) {
+        for ( ; lo < hi; ++lo) {
+
+            const size_t uch = size_t (lo->c);
+
+            if (uch < 256 && masks_ [uch] & UPPER) {
+#if 'A' == 0x41   // ASCII
+                lo->c = UChar (uch - 32);
+#else   // EBCDIC
+                lo->c = UChar (uch + 64);
+#endif
+            }
+        }
+    }
+    else {
+        // FIXME: implement this 
+        RW_ASSERT (!"do_toupper() not implemented");
+    }
+
+    return lo;
+}
+
+
+UserCtype<UserChar>::char_type
+UserCtype<UserChar>::
+do_widen (char ch) const
+{
+    _rw_funcall (*this, mf_widen);
+
+    const UChar uch = UChar (ch);
+
+    _rw_check_char (*this, mf_toupper, uch);
+
+    if (narrow_ && wide_) {
+        for (size_t i = 0; 0 <= narrow_ [i]; ++i) {
+            if (int (uch) == narrow_ [i]) {
+                if (0 <= wide_ [i])
+                    return make_char (char (wide_ [i]), (UserChar*)0);
+
+                if (throw_on_invalid_)
+                    throw;
+
+                break;
+            }
+        }
+    }
+
+    return make_char (ch, (UserChar*)0);
+}
+
+
+const char*
+UserCtype<UserChar>::
+do_widen (const char *lo, const char *hi, char_type *dst) const
+{
+    _rw_funcall (*this, mf_widen_range);
+
+    if (narrow_ && wide_) {
+        for ( ; lo < hi; ++lo, ++dst) {
+
+            const size_t uch = size_t (*lo);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            for (size_t i = 0; 0 <= narrow_ [i]; ++i) {
+                if (int (uch) == narrow_ [i]) {
+                    if (0 <= wide_ [i])
+                        *dst = make_char (char (wide_ [i]), (UserChar*)0);
+
+                    if (throw_on_invalid_)
+                        throw;
+
+                    break;
+                }
+            }
+        }
+    }
+    else {
+        for (; lo < hi; ++lo, ++dst) {
+
+            const UChar uch = UChar (*lo);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            *dst = make_char (*lo, (UserChar*)0);
+        }
+    }
+
+    return lo;
+}
+
+
+char UserCtype<UserChar>::
+do_narrow (char_type ch, char dfault) const
+{
+    _rw_funcall (*this, mf_narrow);
+
+    const size_t uch = size_t (ch.c);
+
+    _rw_check_char (*this, mf_toupper, uch);
+
+    if (narrow_ && wide_) {
+        for (size_t i = 0; 0 <= wide_ [i]; ++i) {
+            if (int (uch) == wide_ [i]) {
+                if (0 <= wide_ [i])
+                    return char (wide_ [i]);
+
+                if (throw_on_invalid_)
+                    throw;
+
+                break;
+            }
+        }
+    }
+
+    return dfault;
+}
+
+
+const UserCtype<UserChar>::char_type*
+UserCtype<UserChar>::
+do_narrow (const char_type *lo, const char_type *hi, char dflt, char *dst) const
+{
+    _rw_funcall (*this, mf_narrow_range);
+
+    if (narrow_ && wide_) {
+        for ( ; lo < hi; ++lo, ++dst) {
+
+            const size_t uch = size_t (lo->c);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            for (size_t i = 0; 0 <= wide_ [i]; ++i) {
+                if (int (uch) == wide_ [i]) {
+                    *dst = 0 <= narrow_ [i] ? char (wide_ [i]) : dflt;
+                    break;
+                }
+            }
+        }
+    }
+    else {
+        for (; lo < hi; ++lo, ++dst) {
+
+            const size_t uch = size_t (lo->c);
+
+            _rw_check_char (*this, mf_toupper, uch);
+
+            *dst = char (uch);
+        }
+    }
+
+    return lo;
+}

Propchange: incubator/stdcxx/trunk/tests/src/ctype.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/tests/src/ctype.cpp
------------------------------------------------------------------------------
    svn:keywords = Id



Mime
View raw message