177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner/*
277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * Copyright (c) 2007 2008
377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * Francois Dumont
477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner *
577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * This material is provided "as is", with absolutely no warranty expressed
677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * or implied. Any use is at your own risk.
777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner *
877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * Permission to use or copy this software for any purpose is hereby granted
977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * without fee, provided the above notices are retained on all copies.
1077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * Permission to modify the code and to distribute modified code is granted,
1177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * provided the above notices are retained, and a notice that the code was
1277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner * modified is included with the above copyright notice.
1377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner *
1477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner */
1577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
1677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#if defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
1777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  define _STLP_WCSNCPY(D, DS, S, C) wcsncpy_s(D, DS, S, C)
1877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#else
1977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#  define _STLP_WCSNCPY(D, DS, S, C) wcsncpy(D, S, C)
2077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner#endif
2177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
2277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerstatic const wchar_t* __wtrue_name = L"true";
2377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerstatic const wchar_t* __wfalse_name = L"false";
2477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
2577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnertypedef struct _Locale_codecvt {
2677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _Locale_lcid_t lc;
2777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  UINT cp;
2877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  unsigned char cleads[256 / CHAR_BIT];
2977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  unsigned char max_char_size;
3077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  DWORD mbtowc_flags;
3177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  DWORD wctomb_flags;
3277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner} _Locale_codecvt_t;
3377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
3477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner/* Ctype */
3577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner_Locale_mask_t _WLocale_ctype(_Locale_ctype_t* ltype, wint_t c,
3677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                              _Locale_mask_t which_bits) {
3777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  wchar_t buf[2];
3877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  WORD out[2];
3977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  buf[0] = c; buf[1] = 0;
4077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  GetStringTypeW(CT_CTYPE1, buf, -1, out);
4177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _STLP_MARK_PARAMETER_AS_UNUSED(ltype)
4277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return (_Locale_mask_t)(MapCtypeMask(out[0]) & which_bits);
4377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
4477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
4577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerwint_t _WLocale_tolower(_Locale_ctype_t* ltype, wint_t c) {
4677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  wchar_t in_c = c;
4777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  wchar_t res;
4877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
4977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  LCMapStringW(ltype->lc.id, LCMAP_LOWERCASE, &in_c, 1, &res, 1);
5077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return res;
5177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
5277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
5377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerwint_t _WLocale_toupper(_Locale_ctype_t* ltype, wint_t c) {
5477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  wchar_t in_c = c;
5577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  wchar_t res;
5677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
5777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  LCMapStringW(ltype->lc.id, LCMAP_UPPERCASE, &in_c, 1, &res, 1);
5877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return res;
5977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
6077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
6177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner_Locale_codecvt_t* _Locale_codecvt_create(const char * name, _Locale_lcid_t* lc_hint, int *__err_code) {
6277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  char cp_name[MAX_CP_LEN + 1];
6377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  unsigned char *ptr;
6477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  CPINFO CPInfo;
6577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  int i;
6677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
6777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _Locale_codecvt_t *lcodecvt = (_Locale_codecvt_t*)malloc(sizeof(_Locale_codecvt_t));
6877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
6977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (!lcodecvt) { *__err_code = _STLP_LOC_NO_MEMORY; return lcodecvt; }
7077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  memset(lcodecvt, 0, sizeof(_Locale_codecvt_t));
7177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
7277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (__GetLCIDFromName(name, &lcodecvt->lc.id, cp_name, lc_hint) == -1)
7377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  { free(lcodecvt); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
7477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
7577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  lcodecvt->cp = atoi(cp_name);
7677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (!GetCPInfo(lcodecvt->cp, &CPInfo)) { free(lcodecvt); return NULL; }
7777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
7877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (lcodecvt->cp != CP_UTF7 && lcodecvt->cp != CP_UTF8) {
7977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    lcodecvt->mbtowc_flags = MB_PRECOMPOSED;
8077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    lcodecvt->wctomb_flags = WC_COMPOSITECHECK | WC_SEPCHARS;
8177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  }
8277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  lcodecvt->max_char_size = CPInfo.MaxCharSize;
8377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
8477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (CPInfo.MaxCharSize > 1) {
8577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    for (ptr = (unsigned char*)CPInfo.LeadByte; *ptr && *(ptr + 1); ptr += 2)
8677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      for (i = *ptr; i <= *(ptr + 1); ++i) lcodecvt->cleads[i / CHAR_BIT] |= (0x01 << i % CHAR_BIT);
8777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  }
8877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
8977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return lcodecvt;
9077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
9177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
9277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerchar const* _Locale_codecvt_name(const _Locale_codecvt_t* lcodecvt, char* buf) {
9377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  char cp_buf[MAX_CP_LEN + 1];
9477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  my_ltoa(lcodecvt->cp, cp_buf);
9577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return __GetLocaleName(lcodecvt->lc.id, cp_buf, buf);
9677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
9777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
9877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnervoid _Locale_codecvt_destroy(_Locale_codecvt_t* lcodecvt) {
9977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (!lcodecvt) return;
10077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
10177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  free(lcodecvt);
10277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
10377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
10477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerint _WLocale_mb_cur_max (_Locale_codecvt_t * lcodecvt)
10577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner{ return lcodecvt->max_char_size; }
10677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
10777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerint _WLocale_mb_cur_min (_Locale_codecvt_t *lcodecvt) {
10877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _STLP_MARK_PARAMETER_AS_UNUSED(lcodecvt)
10977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return 1;
11077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
11177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
11277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerint _WLocale_is_stateless (_Locale_codecvt_t * lcodecvt)
11377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner{ return (lcodecvt->max_char_size == 1) ? 1 : 0; }
11477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
11577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerstatic int __isleadbyte(int i, unsigned char *ctable) {
11677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  unsigned char c = (unsigned char)i;
11777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return (ctable[c / CHAR_BIT] & (0x01 << c % CHAR_BIT));
11877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
11977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
12077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerstatic int __mbtowc(_Locale_codecvt_t *l, wchar_t *dst, const char *from, unsigned int count) {
12177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  int result;
12277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
12377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (l->cp == CP_UTF7 || l->cp == CP_UTF8) {
12477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    result = MultiByteToWideChar(l->cp, l->mbtowc_flags, from, count, dst, 1);
12577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    if (result == 0) {
12677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      switch (GetLastError()) {
12777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        case ERROR_NO_UNICODE_TRANSLATION:
12877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner          return -2;
12977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner        default:
13077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner          return -1;
13177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      }
13277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    }
13377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  }
13477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  else {
13577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    if (count == 1 && __isleadbyte(*from, l->cleads)) return (size_t)-2;
13677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    result = MultiByteToWideChar(l->cp, l->mbtowc_flags, from, count, dst, 1);
13777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    if (result == 0) return -1;
13877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  }
13977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
14077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return result;
14177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
14277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
14377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnersize_t _WLocale_mbtowc(_Locale_codecvt_t *lcodecvt, wchar_t *to,
14477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                       const char *from, size_t n, mbstate_t *shift_state) {
14577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  int result;
14677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _STLP_MARK_PARAMETER_AS_UNUSED(shift_state)
14777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (lcodecvt->max_char_size == 1) { /* Single byte encoding. */
14877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    result = MultiByteToWideChar(lcodecvt->cp, lcodecvt->mbtowc_flags, from, 1, to, 1);
14977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    if (result == 0) return (size_t)-1;
15077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    return result;
15177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  }
15277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  else { /* Multi byte encoding. */
15377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    int retval;
15477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    unsigned int count = 1;
15577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    while (n--) {
15677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      retval = __mbtowc(lcodecvt, to, from, count);
15777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      if (retval == -2)
15877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      { if (++count > ((unsigned int)lcodecvt->max_char_size)) return (size_t)-1; }
15977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      else if (retval == -1)
16077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      { return (size_t)-1; }
16177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      else
16277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      { return count; }
16377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    }
16477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    return (size_t)-2;
16577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  }
16677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
16777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
16877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnersize_t _WLocale_wctomb(_Locale_codecvt_t *lcodecvt, char *to, size_t n,
16977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                       const wchar_t c, mbstate_t *shift_state) {
17077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  int size = WideCharToMultiByte(lcodecvt->cp, lcodecvt->wctomb_flags, &c, 1, NULL, 0, NULL, NULL);
17177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
17277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (!size) return (size_t)-1;
17377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if ((size_t)size > n) return (size_t)-2;
17477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
17577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (n > INT_MAX)
17677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    /* Limiting the output buf size to INT_MAX seems like reasonable to transform a single wchar_t. */
17777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    n = INT_MAX;
17877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
17977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  WideCharToMultiByte(lcodecvt->cp,  lcodecvt->wctomb_flags, &c, 1, to, (int)n, NULL, NULL);
18077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
18177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _STLP_MARK_PARAMETER_AS_UNUSED(shift_state)
18277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return (size_t)size;
18377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
18477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
18577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnersize_t _WLocale_unshift(_Locale_codecvt_t *lcodecvt, mbstate_t *st,
18677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                        char *buf, size_t n, char **next) {
18777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  /* _WLocale_wctomb do not even touch to st, there is nothing to unshift in this localization implementation. */
18877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _STLP_MARK_PARAMETER_AS_UNUSED(lcodecvt)
18977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _STLP_MARK_PARAMETER_AS_UNUSED(st)
19077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _STLP_MARK_PARAMETER_AS_UNUSED(&n)
19177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  *next = buf;
19277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return 0;
19377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
19477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
19577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner/* Collate */
19677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner/* This function takes care of the potential size_t DWORD different size. */
19777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerstatic int _WLocale_strcmp_aux(_Locale_collate_t* lcol,
19877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                               const wchar_t* s1, size_t n1,
19977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                               const wchar_t* s2, size_t n2) {
20077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  int result = CSTR_EQUAL;
20177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  while (n1 > 0 || n2 > 0) {
20277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    DWORD size1 = trim_size_t_to_DWORD(n1);
20377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    DWORD size2 = trim_size_t_to_DWORD(n2);
20477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    result = CompareStringW(lcol->lc.id, 0, s1, size1, s2, size2);
20577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    if (result != CSTR_EQUAL)
20677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      break;
20777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    n1 -= size1;
20877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    n2 -= size2;
20977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  }
21077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return result;
21177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
21277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
21377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerint _WLocale_strcmp(_Locale_collate_t* lcol,
21477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                    const wchar_t* s1, size_t n1,
21577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                    const wchar_t* s2, size_t n2) {
21677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  int result;
21777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  result = _WLocale_strcmp_aux(lcol, s1, n1, s2, n2);
21877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return (result == CSTR_EQUAL) ? 0 : (result == CSTR_LESS_THAN) ? -1 : 1;
21977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
22077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
22177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnersize_t _WLocale_strxfrm(_Locale_collate_t* lcol,
22277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                        wchar_t* dst, size_t dst_size,
22377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                        const wchar_t* src, size_t src_size) {
22477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  int result, i;
22577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
22677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  /* see _Locale_strxfrm: */
22777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (src_size > INT_MAX) {
22877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    if (dst != 0) {
22977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      _STLP_WCSNCPY(dst, dst_size, src, src_size);
23077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    }
23177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    return src_size;
23277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  }
23377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (dst_size > INT_MAX) {
23477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    dst_size = INT_MAX;
23577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  }
23677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  result = LCMapStringW(lcol->lc.id, LCMAP_SORTKEY, src, (int)src_size, dst, (int)dst_size);
23777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  if (result != 0 && dst != 0) {
23877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    for (i = result - 1; i >= 0; --i) {
23977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner      dst[i] = ((unsigned char*)dst)[i];
24077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner    }
24177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  }
24277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return result != 0 ? result - 1 : 0;
24377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
24477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
24577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner/* Numeric */
24677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerwchar_t _WLocale_decimal_point(_Locale_numeric_t* lnum) {
24777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  wchar_t buf[4];
24877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  GetLocaleInfoW(lnum->lc.id, LOCALE_SDECIMAL, buf, 4);
24977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return buf[0];
25077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
25177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
25277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerwchar_t _WLocale_thousands_sep(_Locale_numeric_t* lnum) {
25377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  wchar_t buf[4];
25477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  GetLocaleInfoW(lnum->lc.id, LOCALE_STHOUSAND, buf, 4);
25577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return buf[0];
25677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
25777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
25877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerconst wchar_t * _WLocale_true(_Locale_numeric_t* lnum, wchar_t* buf, size_t bufSize) {
25977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _STLP_MARK_PARAMETER_AS_UNUSED(lnum)
26077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _STLP_MARK_PARAMETER_AS_UNUSED(buf)
26177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _STLP_MARK_PARAMETER_AS_UNUSED(&bufSize)
26277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return __wtrue_name;
26377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
26477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
26577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerconst wchar_t * _WLocale_false(_Locale_numeric_t* lnum, wchar_t* buf, size_t bufSize) {
26677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _STLP_MARK_PARAMETER_AS_UNUSED(lnum)
26777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _STLP_MARK_PARAMETER_AS_UNUSED(buf)
26877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  _STLP_MARK_PARAMETER_AS_UNUSED(&bufSize)
26977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner  return __wfalse_name;
27077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner}
27177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
27277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner/* Monetary */
27377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerconst wchar_t* _WLocale_int_curr_symbol(_Locale_monetary_t * lmon, wchar_t* buf, size_t bufSize)
27477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner{ GetLocaleInfoW(lmon->lc.id, LOCALE_SINTLSYMBOL, buf, (int)bufSize); return buf; }
27577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
27677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerconst wchar_t* _WLocale_currency_symbol(_Locale_monetary_t * lmon, wchar_t* buf, size_t bufSize)
27777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner{ GetLocaleInfoW(lmon->lc.id, LOCALE_SCURRENCY, buf, (int)bufSize); return buf; }
27877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
27977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerwchar_t _WLocale_mon_decimal_point(_Locale_monetary_t * lmon)
28077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner{ return lmon->decimal_point[0]; }
28177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
28277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerwchar_t _WLocale_mon_thousands_sep(_Locale_monetary_t * lmon)
28377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner{ return lmon->thousands_sep[0]; }
28477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
28577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerconst wchar_t* _WLocale_positive_sign(_Locale_monetary_t * lmon, wchar_t* buf, size_t bufSize)
28677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner{ GetLocaleInfoW(lmon->lc.id, LOCALE_SPOSITIVESIGN, buf, (int)bufSize); return buf; }
28777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
28877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerconst wchar_t* _WLocale_negative_sign(_Locale_monetary_t * lmon, wchar_t* buf, size_t bufSize)
28977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner{ GetLocaleInfoW(lmon->lc.id, LOCALE_SNEGATIVESIGN, buf, (int)bufSize); return buf; }
29077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
29177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner/* Time */
29277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerconst wchar_t * _WLocale_full_monthname(_Locale_time_t * ltime, int month,
29377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                                        wchar_t* buf, size_t bufSize)
29477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner{ GetLocaleInfoW(ltime->lc.id, LOCALE_SMONTHNAME1 + month, buf, (int)bufSize); return buf; }
29577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
29677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerconst wchar_t * _WLocale_abbrev_monthname(_Locale_time_t * ltime, int month,
29777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                                          wchar_t* buf, size_t bufSize)
29877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner{ GetLocaleInfoW(ltime->lc.id, LOCALE_SABBREVMONTHNAME1 + month, buf, (int)bufSize); return buf; }
29977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
30077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerconst wchar_t * _WLocale_full_dayofweek(_Locale_time_t * ltime, int day,
30177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                                        wchar_t* buf, size_t bufSize)
30277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner{ GetLocaleInfoW(ltime->lc.id, LOCALE_SDAYNAME1 + day, buf, (int)bufSize); return buf; }
30377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
30477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerconst wchar_t * _WLocale_abbrev_dayofweek(_Locale_time_t * ltime, int day,
30577dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                                          wchar_t* buf, size_t bufSize)
30677dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner{ GetLocaleInfoW(ltime->lc.id, LOCALE_SABBREVDAYNAME1 + day, buf, (int)bufSize); return buf; }
30777dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
30877dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerconst wchar_t* _WLocale_am_str(_Locale_time_t* ltime,
30977dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                               wchar_t* buf, size_t bufSize)
31077dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner{ GetLocaleInfoW(ltime->lc.id, LOCALE_S1159, buf, (int)bufSize); return buf; }
31177dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner
31277dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turnerconst wchar_t* _WLocale_pm_str(_Locale_time_t* ltime,
31377dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner                               wchar_t* buf, size_t bufSize)
31477dc872c5c4ae67e051d1bf7edf96ce36c7b9be2David 'Digit' Turner{ GetLocaleInfoW(ltime->lc.id, LOCALE_S2359, buf, (int)bufSize); return buf; }
315