/*************************************************************************** * * 22.locale.ctype.toupper.cpp - Tests exercising the toupper() of ctype facet * * $Id$ * *************************************************************************** * * 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-2006 Rogue Wave Software. * **************************************************************************/ // DESCRIPTION: test iterates over the locales installed on a machine, // calling the C character classification functions and // their C++ counterpart(s), comparing the results of // the calls against one another. #include #if defined __linux__ // on Linux define _XOPEN_SOURCE to get CODESET defined in # define _XOPEN_SOURCE 500 /* Single Unix conformance */ // bring __int32_t into scope (otherwise fails to compile) # include #endif // __linux__ // see Onyx PR #28150 #if defined (__SUNPRO_CC) && __SUNPRO_CC <= 0x540 # include #endif // defined (__SUNPRO_CC) && __SUNPRO_CC <= 0x540 #include #include #include #include #include #include #include #include // for WEOF, btowc(), wctob() #include // for iswxxx() #if !defined (_WIN32) # if !defined (LC_MESSAGES) # define LC_MESSAGES _RWSTD_LC_MESSAGES # endif // LC_MESSAGES # include #endif // _WIN32 #include #include // for SLASH #include // for rw_locale_query() /**************************************************************************/ // the root of the locale directory (RWSTD_LOCALE_ROOT) // not set here to avoid Solaris 7 putenv() bug (PR #30017) const char* locale_root; #define NLOOPS 25 #define MAX_STR_SIZE 16 #define LOCALES "{{en-US,de-DE,fr-FR,es-ES}-*-{ISO-8859-*,UTF-8,CP125?}," \ "{ja-JP-*-{EUC-JP,SHIFT_JIS,UTF-8,CP125?}}," \ "{zh-CN-*-{GB*,UTF-8,CP125?}}," \ "{ru-RU-*-{KOI*,UTF-8,CP125?}}}" const char* locale_list = 0; #define BEGIN_LOCALE_LOOP(num, locname, loop_cntrl) \ if (!locale_list) locale_list = rw_locale_query (LC_CTYPE, LOCALES); \ for (const char* locname = locale_list; \ locname && *locname; locname += std::strlen (locname) + 1) { \ _TRY { \ const std::locale loc (locname); \ const std::ctype &ctc = \ _STD_USE_FACET (std::ctype, loc); \ _RWSTD_UNUSED (ctc); \ const std::ctype &ctp = \ _STD_USE_FACET (std::ctype, loc); \ for (int loop_cntrl = 0; loop_cntrl < int (num); loop_cntrl++) #define END_LOCALE_LOOP(locname) \ } \ _CATCH (...) { \ rw_assert (0, 0, __LINE__, \ "locale (\"%s\") threw an exception", locname); \ } \ } // for notational convenience typedef unsigned char UChar; #define ALPHA std::ctype_base::alpha #define UPPER std::ctype_base::upper #define LOWER std::ctype_base::lower #define DIGIT std::ctype_base::digit #define SPACE std::ctype_base::space #define CNTRL std::ctype_base::cntrl #define PUNCT std::ctype_base::punct #define XDIGIT std::ctype_base::xdigit #define GRAPH std::ctype_base::graph #define PRINT std::ctype_base::print // wrapper functions for the c library char and wchar_t functions char libc_tolower (char ch) { return std::tolower (UChar (ch)); } char libc_toupper (char ch) { return (std::toupper)(UChar (ch)); } const char* widen (char *dst, const char *src) { if (src == dst || !src || !dst) return src; std::memcpy (dst, src, std::strlen (src) + 1); return dst; } char widen (char, char ch, const char*) { return ch; } #ifndef _RWSTD_NO_WCHAR_T wchar_t libc_tolower (wchar_t ch) { return (std::towlower)(ch); } wchar_t libc_toupper (wchar_t ch) { return (std::towupper)(ch); } const wchar_t* widen (wchar_t *dst, const char *src) { static wchar_t buf [4096]; if (!src) return 0; if (!dst) dst = buf; std::size_t len = std::strlen (src); _RWSTD_ASSERT (len < sizeof buf /sizeof *buf); len = std::mbstowcs (dst, src, sizeof buf / sizeof *buf); if (std::size_t (-1) == len) *dst = 0; return dst; } wchar_t widen (wchar_t, char ch, const char *locname) { char curlocname [256]; std::strcpy (curlocname, std::setlocale (LC_CTYPE, 0)); if (0 == std::setlocale (LC_CTYPE, locname)) return UChar (ch); wchar_t result; #ifndef _RWSTD_NO_BTOWC result = std::btowc (UChar (ch)); #elif !defined (_RWSTD_NO_MBTOWC) if (1 != std::mbtowc (&result, &ch, 1)) result = wchar_t (WEOF); #else result = UChar (ch); #endif // _RWSTD_NO_BTOWC, _RWSTD_NO_MBTOWC if (locname) std::setlocale (LC_CTYPE, curlocname); return result; } #endif // _RWSTD_NO_WCHAR_T /**************************************************************************/ template void test_toupper (charT, const char *cname) { rw_info (0, 0, __LINE__, "std::ctype<%s>::toupper(%1$s)", cname); BEGIN_LOCALE_LOOP (UCHAR_MAX, locname2, i) { const charT ch = charT (i); // set the global C locale to the locale name for the C library call std::setlocale (LC_CTYPE, locname2); const charT uch = libc_toupper (ch); // set the global C locale to default to make sure // the C++ library does not asume a set value std::setlocale (LC_CTYPE, ""); // exercise toupper using ctype<>::toupper () rw_assert (uch == (ctp.toupper)(ch), 0, __LINE__, "ctype<%s>::toupper(%{#lc}) == %{#lc}, got %{#lc} " "in locale(%#s)", cname, ch, uch, (ctp.toupper)(ch), locname2); // exercise toupper using toupper (char, locale) rw_assert (uch == (charT)(std::toupper)(ch, loc), 0, __LINE__, "toupper<%s>(%{#lc}, locale(%#s)) == %{#lc}, got %{#lc}", cname, ch, locname2, uch, (std::toupper)(ch, loc)); } END_LOCALE_LOOP (locname2); } /**************************************************************************/ template void test_libc (charT, const char *cname) { test_toupper (charT (), cname); } /**************************************************************************/ template void test_libstd_toupper (charT, const char *cname, const std::ctype &ct, const char *locname) { rw_info (0, 0, __LINE__, "std::ctype<%s>::toupper(%1$s) in locale(%#s)", cname, locname); int success; #undef TEST #define TEST(lower, upper) \ success = ct.widen (upper) == ct.toupper (ct.widen (lower)); \ rw_assert (success, 0, __LINE__, \ "ctype<%s>::toupper(%d) == %d, got %d", cname, \ lower, upper, ct.toupper((charT)lower)); TEST ('a', 'A'); TEST ('b', 'B'); TEST ('c', 'C'); if (sizeof(charT) > 1) TEST ('\xa0', '\xa1'); #undef TEST } /**************************************************************************/ template void test_libstd (charT, const char *cname) { const char cmap_1[] = { " \"ANSI_X3.4-1968\"\n" " 1\n" " 1\n" "CHARMAP\n" " \\x00\n" " \\x01\n" " \\x02\n" " \\x03\n" " \\x04\n" " \\x05\n" " \\x06\n" " \\x07\n" " \\x08\n" " \\x09\n" " \\x0a\n" " \\x0b\n" " \\x0c\n" " \\x0d\n" " \\x0e\n" " \\x0f\n" " \\x10\n" " \\x11\n" " \\x12\n" " \\x13\n" " \\x14\n" " \\x15\n" " \\x16\n" " \\x17\n" " \\x18\n" " \\x19\n" " \\x1a\n" " \\x1b\n" " \\x1c\n" " \\x1d\n" " \\x1e\n" " \\x1f\n" " \\x20\n" " \\x21\n" " \\x22\n" " \\x23\n" " \\x24\n" " \\x25\n" " \\x26\n" " \\x27\n" " \\x28\n" " \\x29\n" " \\x2a\n" " \\x2b\n" " \\x2c\n" " \\x2d\n" " \\x2e\n" " \\x2f\n" " \\x30\n" " \\x31\n" " \\x32\n" " \\x33\n" " \\x34\n" " \\x35\n" " \\x36\n" " \\x37\n" " \\x38\n" " \\x39\n" " \\x3a\n" " \\x3b\n" " \\x3c\n" " \\x3d\n" " \\x3e\n" " \\x3f\n" " \\x40\n" " \\x41\n" " \\x42\n" " \\x43\n" " \\x44\n" " \\x45\n" " \\x46\n" " \\x47\n" " \\x48\n" " \\x49\n" " \\x4a\n" " \\x4b\n" " \\x4c\n" " \\x4d\n" " \\x4e\n" " \\x4f\n" " \\x50\n" " \\x51\n" " \\x52\n" " \\x53\n" " \\x54\n" " \\x55\n" " \\x56\n" " \\x57\n" " \\x58\n" " \\x59\n" " \\x5a\n" " \\x5b\n" " \\x5c\n" " \\x5d\n" " \\x5e\n" " \\x5f\n" " \\x60\n" " \\x61\n" " \\x62\n" " \\x63\n" " \\x64\n" " \\x65\n" " \\x66\n" " \\x67\n" " \\x68\n" " \\x69\n" " \\x6a\n" " \\x6b\n" " \\x6c\n" " \\x6d\n" " \\x6e\n" " \\x6f\n" " \\x70\n" " \\x71\n" " \\x72\n" " \\x73\n" " \\x74\n" " \\x75\n" " \\x76\n" " \\x77\n" " \\x78\n" " \\x79\n" " \\x7a\n" " \\x7b\n" " \\x7c\n" " \\x7d\n" " \\x7e\n" " \\x7f\n" " \\xa0\n" " \\xa1\n" " \\xa2\n" "END CHARMAP\n" }; const char loc_1[] = { "escape_char /\n" "LC_CTYPE\n" "toupper (,);(,);" "(,);(,)\n" "tolower (,);(,);" "(,);(,)\n" "END LC_CTYPE\n" }; //invoke rw_create_locale to build a locale to test with const char* const locname = rw_create_locale (cmap_1, loc_1); if (!rw_error (0 != locname, 0, __LINE__, "failed to create a locale in %s", locale_root)) return; const std::locale loc (locname); const std::ctype &ct = _STD_USE_FACET (std::ctype, loc); ct._C_opts |= ct._C_use_libstd; ct._C_opts &= ~ct._C_use_libc; test_libstd_toupper (charT (), cname, ct, locname); } /**************************************************************************/ template void run_test (charT, const char *cname) { if (0) { // do a compile time only test on use_facet and has_facet _STD_HAS_FACET (std::ctype_byname, std::locale ()); _STD_USE_FACET (std::ctype_byname, std::locale ()); } test_libc (charT (), cname); test_libstd (charT (), cname); } /**************************************************************************/ static int run_test (int, char**) { run_test (char (), "char"); run_test (wchar_t (), "wchar_t"); return 0; } /**************************************************************************/ int main (int argc, char *argv[]) { return rw_test (argc, argv, __FILE__, "lib.category.ctype", 0 /* no comment */, run_test, "", (void*)0 /* sentinel */); }