c_locale_win32.c

来自「stl的源码」· C语言 代码 · 共 1,787 行 · 第 1/4 页

C
1,787
字号
        else {          /* Known issue: grouping might roll. */          *grouping = *grouping * 10 + *g - '0';        }      }      else if (*g == '0') {        if (!building_group) {          repeat_last = 1;        }        else          /* Known issue: grouping might roll. */          *grouping *= 10;      }      else if (*g == ';') {        /* Stop adding to the current group */        building_group = 0;        ++grouping;      }      /* else we ignore the character */    }    if (!repeat_last)      *grouping++ = CHAR_MAX;    *grouping = 0;  }}const char* __ConvertName(const char* lname, LOCALECONV* ConvTable, int TableSize) {  int i;  int cmp;  int low = 0;  int high = TableSize - 1;  /*  typical binary search - do until no more to search or match */  while (low <= high) {    i = (low + high) / 2;    if ((cmp = lstrcmpiA(lname, (*(ConvTable + i)).name)) == 0)      return (*(ConvTable + i)).abbrev;    else if (cmp < 0)      high = i - 1;    else      low = i + 1;  }  return lname;}int __ParseLocaleString(const char* lname,                        char* lang, char* ctry, char* page) {  int param = 0;  size_t len;  size_t tmpLen;  if (lname[0] == 0)    return 0;  /* We look for the first country separator '_' */  len = strcspn(lname, "_");  if (lname[len] == '_') {    if (len == 0 || len > MAX_LANG_LEN) return -1; /* empty lang is invalid*/    _STLP_STRNCPY(lang, MAX_LANG_LEN + 1, lname, len);    lname += len + 1;    ++param;  }  /* We look for the last code page separator '.' */  len = -1;  tmpLen = strcspn(lname, ".");  while (lname[tmpLen] == '.') {    len = tmpLen; ++tmpLen;    tmpLen += strcspn(lname + tmpLen, ".");  }  if (len != -1) { /* Means that we found a '.' */    if (param == 0) {      /* We have no lang yet so we have to fill it first, no country */      if (len > MAX_LANG_LEN) return -1;      if (len == 0) {        /* No language nor country, only code page */        ++param;      }      else      { _STLP_STRNCPY(lang, MAX_LANG_LEN + 1, lname, len); }      ++param;    }    else {      /* We already have a lang so we are now looking for the country: */      if (len == 0) return -1; /* We forbid locale name with the "_." motif in it */      if (len > MAX_CTRY_LEN) return -1;      _STLP_STRNCPY(ctry, MAX_CTRY_LEN + 1, lname, len);    }    ++param;    lname += len + 1;  }  /* We look for ',' for compatibility with POSIX */  len = strcspn(lname, ",");  switch (param) {    case 0:      if (len > MAX_LANG_LEN) return -1;      _STLP_STRNCPY(lang, MAX_LANG_LEN + 1, lname, len);      break;    case 1:      if (len > MAX_CTRY_LEN) return -1;      _STLP_STRNCPY(ctry, MAX_CTRY_LEN + 1, lname, len);      break;    default:      if (len > MAX_CP_LEN) return -1;      _STLP_STRNCPY(page, MAX_CP_LEN + 1, lname, len);      break;  }  /* ',' POSIX modifier is not used in NT */  return 0;}/* Data necessary for find LCID*/static CRITICAL_SECTION __criticalSection;static int __FindFlag;static LCID __FndLCID;static const char* __FndLang;static const char* __FndCtry;void _Locale_init(){ InitializeCriticalSection(&__criticalSection); }void _Locale_final(){ DeleteCriticalSection(&__criticalSection); }static LCID LocaleFromHex(const char* locale) {  unsigned long result = 0;  int digit;  while (*locale) {    result <<= 4;    digit = (*locale >= '0' && *locale <= '9') ? *locale - '0':            (*locale >= 'A' && *locale <= 'F') ? (*locale - 'A') + 10                                               : (*locale - 'a') + 10;    result += digit;    ++locale;  }  return (LCID)result;}static BOOL CALLBACK EnumLocalesProcA(LPSTR locale) {  LCID lcid = LocaleFromHex(locale);  int LangFlag = 0, CtryFlag = !__FndCtry;  static char Lang[MAX_LANG_LEN], Ctry[MAX_CTRY_LEN];  GetLocaleInfoA(lcid, LOCALE_SENGLANGUAGE, Lang, MAX_LANG_LEN);  if (lstrcmpiA(Lang, __FndLang) != 0) {    GetLocaleInfoA(lcid, LOCALE_SABBREVLANGNAME, Lang, MAX_LANG_LEN);    if (lstrcmpiA(Lang, __FndLang) != 0) {      GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, Lang, MAX_LANG_LEN);      if (lstrcmpiA(Lang, __FndLang) == 0) LangFlag = 1;    }    else LangFlag = 1;  }  else LangFlag = 1;  if (__FndCtry) {    GetLocaleInfoA(lcid, LOCALE_SENGCOUNTRY, Ctry, MAX_CTRY_LEN);    if (lstrcmpiA(Ctry, __FndCtry) != 0) {      GetLocaleInfoA(lcid, LOCALE_SABBREVCTRYNAME, Ctry, MAX_CTRY_LEN);      if (lstrcmpiA(Ctry, __FndCtry) != 0) {        GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, Ctry, MAX_CTRY_LEN);        if (lstrcmpiA(Ctry, __FndCtry) == 0) CtryFlag = 1;      }      else CtryFlag = 1;    }    else      CtryFlag = 1;  }  if (LangFlag && CtryFlag) {    __FindFlag = 1;    __FndLCID = lcid;    return FALSE;  }  return TRUE;}int __GetLCID(const char* lang, const char* ctry, LCID* lcid) {  int ret;  EnterCriticalSection(&__criticalSection);  __FindFlag = 0;  __FndLang = lang;  __FndCtry = ctry;  EnumSystemLocalesA(EnumLocalesProcA, LCID_INSTALLED);  if (__FindFlag != 0) *lcid = __FndLCID;  ret = __FindFlag != 0 ? 0 : -1;  LeaveCriticalSection(&__criticalSection);  return ret;}int __GetLCIDFromName(const char* lname, LCID* lcid, char* cp, _Locale_lcid_t *hint) {  char lang[MAX_LANG_LEN + 1], ctry[MAX_CTRY_LEN + 1], page[MAX_CP_LEN + 1];  int result = 0;  if (lname == NULL || lname[0] == 0) {    *lcid = LOCALE_USER_DEFAULT;    return 0;  }  memset(lang, 0, MAX_LANG_LEN + 1);  memset(ctry, 0, MAX_CTRY_LEN + 1);  memset(page, 0, MAX_CP_LEN + 1);  if (__ParseLocaleString(lname, lang, ctry, page) == -1) return -1;  if (hint != 0) {    *lcid = hint->id;  }  else {    if (lang[0] == 0 && ctry[0] == 0)      *lcid = LOCALE_USER_DEFAULT; /* Only code page given. */    else {      if (ctry[0] == 0) {        result = __GetLCID(__ConvertName(lang, __rg_language, sizeof(__rg_language) / sizeof(LOCALECONV)), NULL, lcid);        if (result != 0) {          /* Check 'C' special case. Check is done after call to __GetLCID because normal programs do not           * generate facet from 'C' name, they use the locale::classic() facets. */          if (lang[0] == 'C' && lang[1] == 0) {            *lcid = INVARIANT_LCID;            result = 0;          }        }      }      else {        result = __GetLCID(__ConvertName(lang, __rg_language, sizeof(__rg_language) / sizeof(LOCALECONV)),                           __ConvertName(ctry, __rg_country, sizeof(__rg_country) / sizeof(LOCALECONV)),                           lcid);        if (result != 0) {          /* Non NLS mapping might introduce problem with some locales when only one entry is mapped,           * the lang or the country (example: chinese locales like 'chinese_taiwan' gives 'CHS_taiwan'           * that do not exists in system). This is why we are giving this locale an other chance by           * calling __GetLCID without the mapping. */          result = __GetLCID(lang, ctry, lcid);        }      }    }  }  if (result == 0) {    /* Handling code page */    if (lstrcmpiA(page, "ACP") == 0 || page[0] == 0)      my_ltoa(__intGetACP(*lcid), cp);    else if (lstrcmpiA(page, "OCP") == 0)      my_ltoa(__intGetOCP(*lcid), cp);    else if (lstrcmpiA(page, "UTF7") == 0)      my_ltoa(CP_UTF7, cp);    else if (lstrcmpiA(page, "UTF8") == 0)      my_ltoa(CP_UTF8, cp);    else      _STLP_STRNCPY(cp, MAX_CP_LEN + 1, page, 5);    /* Code page must be an integer value,     * 0 returned by __intGetACP and 1 returned by __intGetOCP are invalid     * values.     */    if (cp[1] == 0 && (cp[0] == '0' || cp[1] == '1'))      return -1;    else if (atoi(cp) == 0)      return -1;  }  return result;}char const* __GetLocaleName(LCID lcid, const char* cp, char* buf) {  if (lcid == INVARIANT_LCID) {    return _C_name;  }  else {    char lang[MAX_LANG_LEN + 1], ctry[MAX_CTRY_LEN + 1];    GetLocaleInfoA(lcid, LOCALE_SENGLANGUAGE, lang, MAX_LANG_LEN);    GetLocaleInfoA(lcid, LOCALE_SENGCOUNTRY, ctry, MAX_CTRY_LEN);    _STLP_STRCPY(buf, _Locale_MAX_SIMPLE_NAME, lang);    _STLP_STRCAT(buf, _Locale_MAX_SIMPLE_NAME, "_");    _STLP_STRCAT(buf, _Locale_MAX_SIMPLE_NAME, ctry);    _STLP_STRCAT(buf, _Locale_MAX_SIMPLE_NAME, ".");    _STLP_STRCAT(buf, _Locale_MAX_SIMPLE_NAME, cp);    return buf;  }}char const* __Extract_locale_name(const char* loc, const char* category, char* buf) {  char *expr;  size_t len_name;  if (loc[0] == 'L' && loc[1] == 'C' && loc[2] == '_') {    expr = strstr((char*)loc, category);    if (expr == NULL) return NULL; /* Category not found. */    expr = strchr(expr, '=');    if (expr == NULL) return NULL;    ++expr;    len_name = strcspn(expr, ";");    len_name = len_name >= _Locale_MAX_SIMPLE_NAME ? _Locale_MAX_SIMPLE_NAME - 1                                                   : len_name;    _STLP_STRNCPY(buf, _Locale_MAX_SIMPLE_NAME, expr, len_name); buf[len_name] = 0;    return buf;  }  else {    return loc;  }}char const* __TranslateToSystem(const char* lname, char* buf, _Locale_lcid_t* hint,                                int *__err_code) {  LCID lcid;  char cp[MAX_CP_LEN + 1];  if (__GetLCIDFromName(lname, &lcid, cp, hint) != 0)  { *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }  return __GetLocaleName(lcid, cp, buf);}void __GetLocaleInfoUsingACP(LCID lcid, const char* cp, LCTYPE lctype, char* buf, int buf_size, wchar_t* wbuf, int wbuf_size) {  wchar_t *Buffer;  int BufferSize;  int icp;  GetLocaleInfoA(lcid, lctype, buf, buf_size);  icp = atoi(cp);  if (icp != CP_ACP && buf[0] != 0) {    BufferSize = MultiByteToWideChar(CP_ACP, 0, buf, -1, NULL, 0);    if (BufferSize > wbuf_size)    {      Buffer = (wchar_t*)malloc(sizeof(wchar_t) * BufferSize);    }    else    {      Buffer = wbuf;    }    MultiByteToWideChar(CP_ACP, 0, buf, -1, Buffer, BufferSize);    WideCharToMultiByte(icp, 0, Buffer, -1, buf, buf_size, NULL, NULL);    if (Buffer != wbuf)    {      free(Buffer);    }  }}/* Return 0 if ANSI code page not used */int __intGetACP(LCID lcid) {  char cp[6];  if (!GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE, cp, 6)) {#if defined (_STLP_LANG_INVARIANT_DEFINED)    if (lcid == INVARIANT_LCID) {      /* We are using a limited PSDK, we rely on the most common code page */      return 1252;    }#endif    return 0;  }  return atoi(cp);}/* Return 1 if OEM code page not used */int __intGetOCP(LCID lcid) {  char cp[6];  if (!GetLocaleInfoA(lcid, LOCALE_IDEFAULTCODEPAGE, cp, 6))    return 0;  return atoi(cp);}int __GetDefaultCP(LCID lcid) {  int cp = __intGetACP(lcid);  if (cp == 0) return __intGetOCP(lcid);  else return cp;}static int trim_size_t_to_int(size_t n) { return n < (size_t)INT_MAX ? (int)n : INT_MAX; }char* __ConvertToCP(int from_cp, int to_cp, const char *from, size_t size, size_t *ret_buf_size) {  size_t wbuffer_size, buffer_size, from_offset, wbuf_offset;  int from_size, to_size, wbuf_size;  wchar_t *wbuffer;  char* buffer;  size_t orig_size = size;  wbuffer_size = 0;  from_offset = 0;  while (size > 0) {    from_size = trim_size_t_to_int(size);    wbuffer_size += MultiByteToWideChar(from_cp, MB_PRECOMPOSED,                                        from + from_offset, from_size, NULL, 0);    from_offset += from_size;    size -= from_size;  }  wbuffer = (wchar_t*)malloc(sizeof(wchar_t)*wbuffer_size);  size = orig_size;  wbuf_offset = 0;  from_offset = 0;  while (size > 0) {    from_size = trim_size_t_to_int(size);    wbuf_size = trim_size_t_to_int(wbuffer_size - wbuf_offset);    wbuf_offset += MultiByteToWideChar(from_cp, MB_PRECOMPOSED,                                       from + from_offset, from_size, wbuffer + wbuf_offset, wbuf_size);    from_offset += from_size;    size -= from_size;  }  buffer_size = 0;  wbuf_offset = 0;  size = wbuffer_size;  while (size > 0) {    wbuf_size = trim_size_t_to_int(size);    buffer_size += WideCharToMultiByte(to_cp, WC_COMPOSITECHECK | WC_SEPCHARS,                                       wbuffer + wbuf_offset, wbuf_size,                                       NULL, 0, NULL, FALSE);    wbuf_offset += wbuf_size;    size -= wbuf_size;  }  buffer = (char*)malloc(buffer_size);  *ret_buf_size = buffer_size;  size = wbuffer_size;  wbuf_offset = 0;  while (size > 0) {    wbuf_size = trim_size_t_to_int(size);    to_size = trim_size_t_to_int(buffer_size);    buffer_size -= WideCharToMultiByte(to_cp, WC_COMPOSITECHECK | WC_SEPCHARS,                                       wbuffer + wbuf_offset, wbuf_size,                                       buffer, to_size, NULL, FALSE);    wbuf_offset += wbuf_size;    size -= wbuf_size;  }  free(wbuffer);  return buffer;}#ifdef __cplusplus}#endif#ifndef _STLP_NO_WCHAR_T#  include "c_wlocale_win32.c"#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?