Home | History | Annotate | Download | only in bionic
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <wctype.h>
     30 
     31 #include <ctype.h>
     32 #include <errno.h>
     33 #include <stdlib.h>
     34 #include <string.h>
     35 #include <wchar.h>
     36 
     37 #include "private/icu.h"
     38 
     39 enum {
     40   WC_TYPE_INVALID = 0,
     41   WC_TYPE_ALNUM,
     42   WC_TYPE_ALPHA,
     43   WC_TYPE_BLANK,
     44   WC_TYPE_CNTRL,
     45   WC_TYPE_DIGIT,
     46   WC_TYPE_GRAPH,
     47   WC_TYPE_LOWER,
     48   WC_TYPE_PRINT,
     49   WC_TYPE_PUNCT,
     50   WC_TYPE_SPACE,
     51   WC_TYPE_UPPER,
     52   WC_TYPE_XDIGIT,
     53   WC_TYPE_MAX
     54 };
     55 
     56 int iswalnum(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_POSIX_ALNUM, isalnum); }
     57 int iswalpha(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_ALPHABETIC, isalpha); }
     58 int iswblank(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_POSIX_BLANK, isblank); }
     59 int iswgraph(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_POSIX_GRAPH, isgraph); }
     60 int iswlower(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_LOWERCASE, islower); }
     61 int iswprint(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_POSIX_PRINT, isprint); }
     62 int iswspace(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_WHITE_SPACE, isspace); }
     63 int iswupper(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_UPPERCASE, isupper); }
     64 int iswxdigit(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_POSIX_XDIGIT, isxdigit); }
     65 
     66 int iswcntrl(wint_t wc) {
     67   typedef int8_t (*FnT)(UChar32);
     68   static auto u_charType = reinterpret_cast<FnT>(__find_icu_symbol("u_charType"));
     69   return u_charType ? (u_charType(wc) == U_CONTROL_CHAR) : iscntrl(wc);
     70 }
     71 
     72 int iswdigit(wint_t wc) {
     73   typedef UBool (*FnT)(UChar32);
     74   static auto u_isdigit = reinterpret_cast<FnT>(__find_icu_symbol("u_isdigit"));
     75   return u_isdigit ? u_isdigit(wc) : isdigit(wc);
     76 }
     77 
     78 int iswpunct(wint_t wc) {
     79   typedef UBool (*FnT)(UChar32);
     80   static auto u_ispunct = reinterpret_cast<FnT>(__find_icu_symbol("u_ispunct"));
     81   return u_ispunct ? u_ispunct(wc) : ispunct(wc);
     82 }
     83 
     84 int iswalnum_l(wint_t c, locale_t) { return iswalnum(c); }
     85 int iswalpha_l(wint_t c, locale_t) { return iswalpha(c); }
     86 int iswblank_l(wint_t c, locale_t) { return iswblank(c); }
     87 int iswcntrl_l(wint_t c, locale_t) { return iswcntrl(c); }
     88 int iswdigit_l(wint_t c, locale_t) { return iswdigit(c); }
     89 int iswgraph_l(wint_t c, locale_t) { return iswgraph(c); }
     90 int iswlower_l(wint_t c, locale_t) { return iswlower(c); }
     91 int iswprint_l(wint_t c, locale_t) { return iswprint(c); }
     92 int iswpunct_l(wint_t c, locale_t) { return iswpunct(c); }
     93 int iswspace_l(wint_t c, locale_t) { return iswspace(c); }
     94 int iswupper_l(wint_t c, locale_t) { return iswupper(c); }
     95 int iswxdigit_l(wint_t c, locale_t) { return iswxdigit(c); }
     96 
     97 int iswctype(wint_t wc, wctype_t char_class) {
     98   switch (char_class) {
     99     case WC_TYPE_ALNUM: return iswalnum(wc);
    100     case WC_TYPE_ALPHA: return iswalpha(wc);
    101     case WC_TYPE_BLANK: return iswblank(wc);
    102     case WC_TYPE_CNTRL: return iswcntrl(wc);
    103     case WC_TYPE_DIGIT: return iswdigit(wc);
    104     case WC_TYPE_GRAPH: return iswgraph(wc);
    105     case WC_TYPE_LOWER: return iswlower(wc);
    106     case WC_TYPE_PRINT: return iswprint(wc);
    107     case WC_TYPE_PUNCT: return iswpunct(wc);
    108     case WC_TYPE_SPACE: return iswspace(wc);
    109     case WC_TYPE_UPPER: return iswupper(wc);
    110     case WC_TYPE_XDIGIT: return iswxdigit(wc);
    111     default: return 0;
    112   }
    113 }
    114 
    115 int iswctype_l(wint_t wc, wctype_t char_class, locale_t) {
    116   return iswctype(wc, char_class);
    117 }
    118 
    119 wint_t towlower(wint_t wc) {
    120   typedef UChar32 (*FnT)(UChar32);
    121   static auto u_tolower = reinterpret_cast<FnT>(__find_icu_symbol("u_tolower"));
    122   return u_tolower ? u_tolower(wc) : tolower(wc);
    123 }
    124 
    125 wint_t towupper(wint_t wc) {
    126   typedef UChar32 (*FnT)(UChar32);
    127   static auto u_toupper = reinterpret_cast<FnT>(__find_icu_symbol("u_toupper"));
    128   return u_toupper ? u_toupper(wc) : toupper(wc);
    129 }
    130 
    131 wint_t towupper_l(wint_t c, locale_t) { return towupper(c); }
    132 wint_t towlower_l(wint_t c, locale_t) { return towlower(c); }
    133 
    134 wctype_t wctype(const char* property) {
    135   static const char* const  properties[WC_TYPE_MAX] = {
    136     "<invalid>",
    137     "alnum", "alpha", "blank", "cntrl", "digit", "graph",
    138     "lower", "print", "punct", "space", "upper", "xdigit"
    139   };
    140   for (size_t i = 0; i < WC_TYPE_MAX; ++i) {
    141     if (!strcmp(properties[i], property)) {
    142       return static_cast<wctype_t>(i);
    143     }
    144   }
    145   return static_cast<wctype_t>(0);
    146 }
    147 
    148 wctype_t wctype_l(const char* property, locale_t) {
    149   return wctype(property);
    150 }
    151 
    152 static wctrans_t wctrans_tolower = wctrans_t(1);
    153 static wctrans_t wctrans_toupper = wctrans_t(2);
    154 
    155 wctrans_t wctrans(const char* name) {
    156   if (strcmp(name, "tolower") == 0) return wctrans_tolower;
    157   if (strcmp(name, "toupper") == 0) return wctrans_toupper;
    158   return nullptr;
    159 }
    160 
    161 wctrans_t wctrans_l(const char* name, locale_t) {
    162   return wctrans(name);
    163 }
    164 
    165 wint_t towctrans(wint_t c, wctrans_t t) {
    166   if (t == wctrans_tolower) return towlower(c);
    167   if (t == wctrans_toupper) return towupper(c);
    168   errno = EINVAL;
    169   return 0;
    170 }
    171 
    172 wint_t towctrans_l(wint_t c, wctrans_t t, locale_t) {
    173   return towctrans(c, t);
    174 }
    175