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 + -
显示快捷键?