build/stlport/src/c_locale_win32/c_wlocale_win32.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /*
     2  * Copyright (c) 2007 2008
     3  * Francois Dumont
     4  *
     5  * This material is provided "as is", with absolutely no warranty expressed
     6  * or implied. Any use is at your own risk.
     7  *
     8  * Permission to use or copy this software for any purpose is hereby granted
     9  * without fee, provided the above notices are retained on all copies.
    10  * Permission to modify the code and to distribute modified code is granted,
    11  * provided the above notices are retained, and a notice that the code was
    12  * modified is included with the above copyright notice.
    13  *
    14  */
    16 #if defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
    17 #  define _STLP_WCSNCPY(D, DS, S, C) wcsncpy_s(D, DS, S, C)
    18 #else
    19 #  define _STLP_WCSNCPY(D, DS, S, C) wcsncpy(D, S, C)
    20 #endif
    22 static const wchar_t* __wtrue_name = L"true";
    23 static const wchar_t* __wfalse_name = L"false";
    25 typedef struct _Locale_codecvt {
    26   _Locale_lcid_t lc;
    27   UINT cp;
    28   unsigned char cleads[256 / CHAR_BIT];
    29   unsigned char max_char_size;
    30   DWORD mbtowc_flags;
    31   DWORD wctomb_flags;
    32 } _Locale_codecvt_t;
    34 /* Ctype */
    35 _Locale_mask_t _WLocale_ctype(_Locale_ctype_t* ltype, wint_t c,
    36                               _Locale_mask_t which_bits) {
    37   wchar_t buf[2];
    38   WORD out[2];
    39   buf[0] = c; buf[1] = 0;
    40   GetStringTypeW(CT_CTYPE1, buf, -1, out);
    41   _STLP_MARK_PARAMETER_AS_UNUSED(ltype)
    42   return (_Locale_mask_t)(MapCtypeMask(out[0]) & which_bits);
    43 }
    45 wint_t _WLocale_tolower(_Locale_ctype_t* ltype, wint_t c) {
    46   wchar_t in_c = c;
    47   wchar_t res;
    49   LCMapStringW(ltype->lc.id, LCMAP_LOWERCASE, &in_c, 1, &res, 1);
    50   return res;
    51 }
    53 wint_t _WLocale_toupper(_Locale_ctype_t* ltype, wint_t c) {
    54   wchar_t in_c = c;
    55   wchar_t res;
    57   LCMapStringW(ltype->lc.id, LCMAP_UPPERCASE, &in_c, 1, &res, 1);
    58   return res;
    59 }
    61 _Locale_codecvt_t* _Locale_codecvt_create(const char * name, _Locale_lcid_t* lc_hint, int *__err_code) {
    62   char cp_name[MAX_CP_LEN + 1];
    63   unsigned char *ptr;
    64   CPINFO CPInfo;
    65   int i;
    67   _Locale_codecvt_t *lcodecvt = (_Locale_codecvt_t*)malloc(sizeof(_Locale_codecvt_t));
    69   if (!lcodecvt) { *__err_code = _STLP_LOC_NO_MEMORY; return lcodecvt; }
    70   memset(lcodecvt, 0, sizeof(_Locale_codecvt_t));
    72   if (__GetLCIDFromName(name, &lcodecvt->lc.id, cp_name, lc_hint) == -1)
    73   { free(lcodecvt); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
    75   lcodecvt->cp = atoi(cp_name);
    76   if (!GetCPInfo(lcodecvt->cp, &CPInfo)) { free(lcodecvt); return NULL; }
    78   if (lcodecvt->cp != CP_UTF7 && lcodecvt->cp != CP_UTF8) {
    79     lcodecvt->mbtowc_flags = MB_PRECOMPOSED;
    80     lcodecvt->wctomb_flags = WC_COMPOSITECHECK | WC_SEPCHARS;
    81   }
    82   lcodecvt->max_char_size = CPInfo.MaxCharSize;
    84   if (CPInfo.MaxCharSize > 1) {
    85     for (ptr = (unsigned char*)CPInfo.LeadByte; *ptr && *(ptr + 1); ptr += 2)
    86       for (i = *ptr; i <= *(ptr + 1); ++i) lcodecvt->cleads[i / CHAR_BIT] |= (0x01 << i % CHAR_BIT);
    87   }
    89   return lcodecvt;
    90 }
    92 char const* _Locale_codecvt_name(const _Locale_codecvt_t* lcodecvt, char* buf) {
    93   char cp_buf[MAX_CP_LEN + 1];
    94   my_ltoa(lcodecvt->cp, cp_buf);
    95   return __GetLocaleName(lcodecvt->lc.id, cp_buf, buf);
    96 }
    98 void _Locale_codecvt_destroy(_Locale_codecvt_t* lcodecvt) {
    99   if (!lcodecvt) return;
   101   free(lcodecvt);
   102 }
   104 int _WLocale_mb_cur_max (_Locale_codecvt_t * lcodecvt)
   105 { return lcodecvt->max_char_size; }
   107 int _WLocale_mb_cur_min (_Locale_codecvt_t *lcodecvt) {
   108   _STLP_MARK_PARAMETER_AS_UNUSED(lcodecvt)
   109   return 1;
   110 }
   112 int _WLocale_is_stateless (_Locale_codecvt_t * lcodecvt)
   113 { return (lcodecvt->max_char_size == 1) ? 1 : 0; }
   115 static int __isleadbyte(int i, unsigned char *ctable) {
   116   unsigned char c = (unsigned char)i;
   117   return (ctable[c / CHAR_BIT] & (0x01 << c % CHAR_BIT));
   118 }
   120 static int __mbtowc(_Locale_codecvt_t *l, wchar_t *dst, const char *from, unsigned int count) {
   121   int result;
   123   if (l->cp == CP_UTF7 || l->cp == CP_UTF8) {
   124     result = MultiByteToWideChar(l->cp, l->mbtowc_flags, from, count, dst, 1);
   125     if (result == 0) {
   126       switch (GetLastError()) {
   127         case ERROR_NO_UNICODE_TRANSLATION:
   128           return -2;
   129         default:
   130           return -1;
   131       }
   132     }
   133   }
   134   else {
   135     if (count == 1 && __isleadbyte(*from, l->cleads)) return (size_t)-2;
   136     result = MultiByteToWideChar(l->cp, l->mbtowc_flags, from, count, dst, 1);
   137     if (result == 0) return -1;
   138   }
   140   return result;
   141 }
   143 size_t _WLocale_mbtowc(_Locale_codecvt_t *lcodecvt, wchar_t *to,
   144                        const char *from, size_t n, mbstate_t *shift_state) {
   145   int result;
   146   _STLP_MARK_PARAMETER_AS_UNUSED(shift_state)
   147   if (lcodecvt->max_char_size == 1) { /* Single byte encoding. */
   148     result = MultiByteToWideChar(lcodecvt->cp, lcodecvt->mbtowc_flags, from, 1, to, 1);
   149     if (result == 0) return (size_t)-1;
   150     return result;
   151   }
   152   else { /* Multi byte encoding. */
   153     int retval;
   154     unsigned int count = 1;
   155     while (n--) {
   156       retval = __mbtowc(lcodecvt, to, from, count);
   157       if (retval == -2)
   158       { if (++count > ((unsigned int)lcodecvt->max_char_size)) return (size_t)-1; }
   159       else if (retval == -1)
   160       { return (size_t)-1; }
   161       else
   162       { return count; }
   163     }
   164     return (size_t)-2;
   165   }
   166 }
   168 size_t _WLocale_wctomb(_Locale_codecvt_t *lcodecvt, char *to, size_t n,
   169                        const wchar_t c, mbstate_t *shift_state) {
   170   int size = WideCharToMultiByte(lcodecvt->cp, lcodecvt->wctomb_flags, &c, 1, NULL, 0, NULL, NULL);
   172   if (!size) return (size_t)-1;
   173   if ((size_t)size > n) return (size_t)-2;
   175   if (n > INT_MAX)
   176     /* Limiting the output buf size to INT_MAX seems like reasonable to transform a single wchar_t. */
   177     n = INT_MAX;
   179   WideCharToMultiByte(lcodecvt->cp,  lcodecvt->wctomb_flags, &c, 1, to, (int)n, NULL, NULL);
   181   _STLP_MARK_PARAMETER_AS_UNUSED(shift_state)
   182   return (size_t)size;
   183 }
   185 size_t _WLocale_unshift(_Locale_codecvt_t *lcodecvt, mbstate_t *st,
   186                         char *buf, size_t n, char **next) {
   187   /* _WLocale_wctomb do not even touch to st, there is nothing to unshift in this localization implementation. */
   188   _STLP_MARK_PARAMETER_AS_UNUSED(lcodecvt)
   189   _STLP_MARK_PARAMETER_AS_UNUSED(st)
   190   _STLP_MARK_PARAMETER_AS_UNUSED(&n)
   191   *next = buf;
   192   return 0;
   193 }
   195 /* Collate */
   196 /* This function takes care of the potential size_t DWORD different size. */
   197 static int _WLocale_strcmp_aux(_Locale_collate_t* lcol,
   198                                const wchar_t* s1, size_t n1,
   199                                const wchar_t* s2, size_t n2) {
   200   int result = CSTR_EQUAL;
   201   while (n1 > 0 || n2 > 0) {
   202     DWORD size1 = trim_size_t_to_DWORD(n1);
   203     DWORD size2 = trim_size_t_to_DWORD(n2);
   204     result = CompareStringW(lcol->lc.id, 0, s1, size1, s2, size2);
   205     if (result != CSTR_EQUAL)
   206       break;
   207     n1 -= size1;
   208     n2 -= size2;
   209   }
   210   return result;
   211 }
   213 int _WLocale_strcmp(_Locale_collate_t* lcol,
   214                     const wchar_t* s1, size_t n1,
   215                     const wchar_t* s2, size_t n2) {
   216   int result;
   217   result = _WLocale_strcmp_aux(lcol, s1, n1, s2, n2);
   218   return (result == CSTR_EQUAL) ? 0 : (result == CSTR_LESS_THAN) ? -1 : 1;
   219 }
   221 size_t _WLocale_strxfrm(_Locale_collate_t* lcol,
   222                         wchar_t* dst, size_t dst_size,
   223                         const wchar_t* src, size_t src_size) {
   224   int result, i;
   226   /* see _Locale_strxfrm: */
   227   if (src_size > INT_MAX) {
   228     if (dst != 0) {
   229       _STLP_WCSNCPY(dst, dst_size, src, src_size);
   230     }
   231     return src_size;
   232   }
   233   if (dst_size > INT_MAX) {
   234     dst_size = INT_MAX;
   235   }
   236   result = LCMapStringW(lcol->lc.id, LCMAP_SORTKEY, src, (int)src_size, dst, (int)dst_size);
   237   if (result != 0 && dst != 0) {
   238     for (i = result - 1; i >= 0; --i) {
   239       dst[i] = ((unsigned char*)dst)[i];
   240     }
   241   }
   242   return result != 0 ? result - 1 : 0;
   243 }
   245 /* Numeric */
   246 wchar_t _WLocale_decimal_point(_Locale_numeric_t* lnum) {
   247   wchar_t buf[4];
   248   GetLocaleInfoW(lnum->lc.id, LOCALE_SDECIMAL, buf, 4);
   249   return buf[0];
   250 }
   252 wchar_t _WLocale_thousands_sep(_Locale_numeric_t* lnum) {
   253   wchar_t buf[4];
   254   GetLocaleInfoW(lnum->lc.id, LOCALE_STHOUSAND, buf, 4);
   255   return buf[0];
   256 }
   258 const wchar_t * _WLocale_true(_Locale_numeric_t* lnum, wchar_t* buf, size_t bufSize) {
   259   _STLP_MARK_PARAMETER_AS_UNUSED(lnum)
   260   _STLP_MARK_PARAMETER_AS_UNUSED(buf)
   261   _STLP_MARK_PARAMETER_AS_UNUSED(&bufSize)
   262   return __wtrue_name;
   263 }
   265 const wchar_t * _WLocale_false(_Locale_numeric_t* lnum, wchar_t* buf, size_t bufSize) {
   266   _STLP_MARK_PARAMETER_AS_UNUSED(lnum)
   267   _STLP_MARK_PARAMETER_AS_UNUSED(buf)
   268   _STLP_MARK_PARAMETER_AS_UNUSED(&bufSize)
   269   return __wfalse_name;
   270 }
   272 /* Monetary */
   273 const wchar_t* _WLocale_int_curr_symbol(_Locale_monetary_t * lmon, wchar_t* buf, size_t bufSize)
   274 { GetLocaleInfoW(lmon->lc.id, LOCALE_SINTLSYMBOL, buf, (int)bufSize); return buf; }
   276 const wchar_t* _WLocale_currency_symbol(_Locale_monetary_t * lmon, wchar_t* buf, size_t bufSize)
   277 { GetLocaleInfoW(lmon->lc.id, LOCALE_SCURRENCY, buf, (int)bufSize); return buf; }
   279 wchar_t _WLocale_mon_decimal_point(_Locale_monetary_t * lmon)
   280 { return lmon->decimal_point[0]; }
   282 wchar_t _WLocale_mon_thousands_sep(_Locale_monetary_t * lmon)
   283 { return lmon->thousands_sep[0]; }
   285 const wchar_t* _WLocale_positive_sign(_Locale_monetary_t * lmon, wchar_t* buf, size_t bufSize)
   286 { GetLocaleInfoW(lmon->lc.id, LOCALE_SPOSITIVESIGN, buf, (int)bufSize); return buf; }
   288 const wchar_t* _WLocale_negative_sign(_Locale_monetary_t * lmon, wchar_t* buf, size_t bufSize)
   289 { GetLocaleInfoW(lmon->lc.id, LOCALE_SNEGATIVESIGN, buf, (int)bufSize); return buf; }
   291 /* Time */
   292 const wchar_t * _WLocale_full_monthname(_Locale_time_t * ltime, int month,
   293                                         wchar_t* buf, size_t bufSize)
   294 { GetLocaleInfoW(ltime->lc.id, LOCALE_SMONTHNAME1 + month, buf, (int)bufSize); return buf; }
   296 const wchar_t * _WLocale_abbrev_monthname(_Locale_time_t * ltime, int month,
   297                                           wchar_t* buf, size_t bufSize)
   298 { GetLocaleInfoW(ltime->lc.id, LOCALE_SABBREVMONTHNAME1 + month, buf, (int)bufSize); return buf; }
   300 const wchar_t * _WLocale_full_dayofweek(_Locale_time_t * ltime, int day,
   301                                         wchar_t* buf, size_t bufSize)
   302 { GetLocaleInfoW(ltime->lc.id, LOCALE_SDAYNAME1 + day, buf, (int)bufSize); return buf; }
   304 const wchar_t * _WLocale_abbrev_dayofweek(_Locale_time_t * ltime, int day,
   305                                           wchar_t* buf, size_t bufSize)
   306 { GetLocaleInfoW(ltime->lc.id, LOCALE_SABBREVDAYNAME1 + day, buf, (int)bufSize); return buf; }
   308 const wchar_t* _WLocale_am_str(_Locale_time_t* ltime,
   309                                wchar_t* buf, size_t bufSize)
   310 { GetLocaleInfoW(ltime->lc.id, LOCALE_S1159, buf, (int)bufSize); return buf; }
   312 const wchar_t* _WLocale_pm_str(_Locale_time_t* ltime,
   313                                wchar_t* buf, size_t bufSize)
   314 { GetLocaleInfoW(ltime->lc.id, LOCALE_S2359, buf, (int)bufSize); return buf; }

mercurial