c_locale_win32.c

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

C
1,787
字号
/* * Copyright (c) 1999 * Silicon Graphics Computer Systems, Inc. * * Copyright (c) 1999 * Boris Fomitchev * * Written 2000 * Anton Lapach * * This material is provided "as is", with absolutely no warranty expressed * or implied. Any use is at your own risk. * * Permission to use or copy this software for any purpose is hereby granted * without fee, provided the above notices are retained on all copies. * Permission to modify the code and to distribute modified code is granted, * provided the above notices are retained, and a notice that the code was * modified is included with the above copyright notice. * */#include <limits.h>#if defined (_STLP_MSVC) || defined (__ICL)#  include <memory.h>#endif#include <string.h>#include <locale.h>#include <stdlib.h>#include <stdio.h>#if defined (_STLP_USE_SAFE_STRING_FUNCTIONS)#  define _STLP_STRCPY(D, DS, S) strcpy_s(D, DS, S)#  define _STLP_STRNCPY(D, DS, S, C) strncpy_s(D, DS, S, C)#  define _STLP_STRCAT(D, DS, S) strcat_s(D, DS, S)#else#  define _STLP_STRCPY(D, DS, S) strcpy(D, S)#  define _STLP_STRNCPY(D, DS, S, C) strncpy(D, S, C)#  define _STLP_STRCAT(D, DS, S) strcat(D, S)#endif#if defined (__cplusplus)extern "C" {#endif/* Framework functions *//*  locale :: "lang[_country[.code_page]]"  | ".code_page"  | ""  | NULL*/typedef struct _LOCALECONV {  const char* name;  const char* abbrev;} LOCALECONV;#define MAX_LANG_LEN        64  /* max language name length */#define MAX_CTRY_LEN        64  /* max country name length */#define MAX_MODIFIER_LEN    0   /* max modifier name length - n/a */#define MAX_LC_LEN          (MAX_LANG_LEN+MAX_CTRY_LEN+MAX_MODIFIER_LEN+3)                                /* max entire locale string length */#define MAX_CP_LEN          5   /* max code page name length */#if !defined (LANG_INVARIANT)#  define LANG_INVARIANT 0x7f#  define _STLP_LANG_INVARIANT_DEFINED#endif#ifndef CP_UTF7#  define CP_UTF7 65000#endif#ifndef CP_UTF8#  define CP_UTF8 65001#endif#define INVARIANT_LCID MAKELCID(MAKELANGID(LANG_INVARIANT, SUBLANG_NEUTRAL), SORT_DEFAULT)static const char *_C_name = "C";/*  non-NLS language string table */static LOCALECONV __rg_language[] = {  {"american",                    "ENU"},  {"american english",            "ENU"},  {"american-english",            "ENU"},  {"australian",                  "ENA"},  {"belgian",                     "NLB"},  {"canadian",                    "ENC"},  {"chh",                         "ZHH"},  {"chi",                         "ZHI"},  {"chinese",                     "CHS"},  {"chinese-hongkong",            "ZHH"},  {"chinese-simplified",          "CHS"},  {"chinese-singapore",           "ZHI"},  {"chinese-traditional",         "CHT"},  {"dutch-belgian",               "NLB"},  {"english-american",            "ENU"},  {"english-aus",                 "ENA"},  {"english-belize",              "ENL"},  {"english-can",                 "ENC"},  {"english-caribbean",           "ENB"},  {"english-ire",                 "ENI"},  {"english-jamaica",             "ENJ"},  {"english-nz",                  "ENZ"},  {"english-south africa",        "ENS"},  {"english-trinidad y tobago",   "ENT"},  {"english-uk",                  "ENG"},  {"english-us",                  "ENU"},  {"english-usa",                 "ENU"},  {"french-belgian",              "FRB"},  {"french-canadian",             "FRC"},  {"french-luxembourg",           "FRL"},  {"french-swiss",                "FRS"},  {"german-austrian",             "DEA"},  {"german-lichtenstein",         "DEC"},  {"german-luxembourg",           "DEL"},  {"german-swiss",                "DES"},  {"irish-english",               "ENI"},  {"italian-swiss",               "ITS"},  {"norwegian",                   "NOR"},  {"norwegian-bokmal",            "NOR"},  {"norwegian-nynorsk",           "NON"},  {"portuguese-brazilian",        "PTB"},  {"spanish-argentina",           "ESS"},  {"spanish-bolivia",             "ESB"},  {"spanish-chile",               "ESL"},  {"spanish-colombia",            "ESO"},  {"spanish-costa rica",          "ESC"},  {"spanish-dominican republic",  "ESD"},  {"spanish-ecuador",             "ESF"},  {"spanish-el salvador",         "ESE"},  {"spanish-guatemala",           "ESG"},  {"spanish-honduras",            "ESH"},  {"spanish-mexican",             "ESM"},  {"spanish-modern",              "ESN"},  {"spanish-nicaragua",           "ESI"},  {"spanish-panama",              "ESA"},  {"spanish-paraguay",            "ESZ"},  {"spanish-peru",                "ESR"},  {"spanish-puerto rico",         "ESU"},  {"spanish-uruguay",             "ESY"},  {"spanish-venezuela",           "ESV"},  {"swedish-finland",             "SVF"},  {"swiss",                       "DES"},  {"uk",                          "ENG"},  {"us",                          "ENU"},  {"usa",                         "ENU"}};/*  non-NLS country string table */static LOCALECONV __rg_country[] = {  {"america",                     "USA"},  {"britain",                     "GBR"},  {"china",                       "CHN"},  {"czech",                       "CZE"},  {"england",                     "GBR"},  {"great britain",               "GBR"},  {"holland",                     "NLD"},  {"hong-kong",                   "HKG"},  {"new-zealand",                 "NZL"},  {"nz",                          "NZL"},  {"pr china",                    "CHN"},  {"pr-china",                    "CHN"},  {"puerto-rico",                 "PRI"},  {"slovak",                      "SVK"},  {"south africa",                "ZAF"},  {"south korea",                 "KOR"},  {"south-africa",                "ZAF"},  {"south-korea",                 "KOR"},  {"trinidad & tobago",           "TTO"},  {"uk",                          "GBR"},  {"united-kingdom",              "GBR"},  {"united-states",               "USA"},  {"us",                          "USA"},};typedef struct _Locale_name_hint {  LCID id;} _Locale_lcid_t;typedef struct _Locale_ctype {  _Locale_lcid_t lc;  UINT cp;  unsigned short ctable[256];} _Locale_ctype_t;typedef struct _Locale_numeric {  _Locale_lcid_t lc;  char cp[MAX_CP_LEN + 1];  char decimal_point[4];  char thousands_sep[4];  char *grouping;} _Locale_numeric_t;typedef struct _Locale_time {  _Locale_lcid_t lc;  char cp[MAX_CP_LEN + 1];  char *month[12];  char *abbrev_month[12];  char *dayofweek[7];  char *abbrev_dayofweek[7];  char *date_time_format;  char *long_date_time_format;  char *date_format;  char *long_date_format;  char *time_format;  char am[9];  char pm[9];} _Locale_time_t;typedef struct _Locale_collate {  _Locale_lcid_t lc;  char cp[MAX_CP_LEN + 1];} _Locale_collate_t;typedef struct _Locale_monetary {  _Locale_lcid_t lc;  char cp[MAX_CP_LEN + 1];  char decimal_point[4];  char thousands_sep[4];  char *grouping;  char int_curr_symbol[5]; /* 3 + 1 + 1 */  char curr_symbol[6];  char negative_sign[5];  char positive_sign[5];  int frac_digits;  int int_frac_digits;} _Locale_monetary_t;/* Internal function */static void __FixGrouping(char *grouping);static const char* __ConvertName(const char* lname, LOCALECONV* ConvTable, int TableSize);static int __ParseLocaleString(const char* lname, char* lang, char* ctry, char* page);static int __GetLCID(const char* lang, const char* ctry, LCID* lcid);static int __GetLCIDFromName(const char* lname, LCID* lcid, char *cp, _Locale_lcid_t *hint);static char const* __GetLocaleName(LCID lcid, const char* cp, char* buf);static char const* __Extract_locale_name(const char* loc, const char* category, char* buf);static char const* __TranslateToSystem(const char* lname, char* buf, _Locale_lcid_t* hint, int *__err_code);static void __GetLocaleInfoUsingACP(LCID lcid, const char* cp, LCTYPE lctype, char* buf, int buf_size, wchar_t* wbuf, int wbuf_size);static int __intGetACP(LCID lcid);static int __intGetOCP(LCID lcid);static int __GetDefaultCP(LCID lcid);static char* __ConvertToCP(int from_cp, int to_cp, const char *from, size_t size, size_t *ret_buf_size);static void my_ltoa(long __x, char* buf);void my_ltoa(long __x, char* buf) {  char rbuf[64];  char* ptr = rbuf;  if (__x == 0)    *ptr++ = '0';  else {    for (; __x != 0; __x /= 10)      *ptr++ = (char)(__x % 10) + '0';  }  while(ptr > rbuf) *buf++ = *--ptr;  /* psw */  *buf = '\0';}#if defined (__cplusplus)_STLP_BEGIN_NAMESPACEextern "C" {#endif_Locale_lcid_t* _Locale_get_ctype_hint(_Locale_ctype_t* ltype){ return (ltype != 0) ? &ltype->lc : 0; }_Locale_lcid_t* _Locale_get_numeric_hint(_Locale_numeric_t* lnumeric){ return (lnumeric != 0) ? &lnumeric->lc : 0; }_Locale_lcid_t* _Locale_get_time_hint(_Locale_time_t* ltime){ return (ltime != 0) ? &ltime->lc : 0; }_Locale_lcid_t* _Locale_get_collate_hint(_Locale_collate_t* lcollate){ return (lcollate != 0) ? &lcollate->lc : 0; }_Locale_lcid_t* _Locale_get_monetary_hint(_Locale_monetary_t* lmonetary){ return (lmonetary != 0) ? &lmonetary->lc : 0; }_Locale_lcid_t* _Locale_get_messages_hint(struct _Locale_messages* lmessages) {  _STLP_MARK_PARAMETER_AS_UNUSED(lmessages)  return 0;}#define MAP(x, y) if ((mask & x) != 0) ret |= (y)unsigned short MapCtypeMask(unsigned short mask) {  unsigned short ret = 0;  MAP(C1_UPPER, _Locale_UPPER | _Locale_PRINT);  MAP(C1_LOWER, _Locale_LOWER | _Locale_PRINT);  MAP(C1_DIGIT, _Locale_DIGIT | _Locale_PRINT);  MAP(C1_SPACE, _Locale_SPACE | _Locale_PRINT);  MAP(C1_PUNCT, _Locale_PUNCT | _Locale_PRINT);  /* MAP(C1_BLANK, ?); */  MAP(C1_XDIGIT, _Locale_XDIGIT | _Locale_PRINT);  MAP(C1_ALPHA, _Locale_ALPHA | _Locale_PRINT);  if ((mask & C1_CNTRL) != 0) { ret |= _Locale_CNTRL; ret &= ~_Locale_PRINT; }  return ret;}static void MapCtypeMasks(unsigned short *cur, unsigned short *end) {  for (; cur != end; ++cur) {    *cur = MapCtypeMask(*cur);  }}_Locale_ctype_t* _Locale_ctype_create(const char * name, _Locale_lcid_t* lc_hint, int *__err_code) {  char cp_name[MAX_CP_LEN + 1];  int NativeCP;  unsigned char Buffer[256];  unsigned char *ptr;  CPINFO CPInfo;  int i;  wchar_t *wbuffer;  int BufferSize;  _Locale_ctype_t *ltype = (_Locale_ctype_t*)malloc(sizeof(_Locale_ctype_t));  if (!ltype) { *__err_code = _STLP_LOC_NO_MEMORY; return ltype; }  memset(ltype, 0, sizeof(_Locale_ctype_t));  if (__GetLCIDFromName(name, &ltype->lc.id, cp_name, lc_hint) == -1)  { free(ltype); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }#if defined (__BORLANDC__)  if ( ltype->lc.id == INVARIANT_LCID && name[0] == 'C' && name[1] == 0 )  { ltype->lc.id = 0x409; }#endif  ltype->cp = atoi(cp_name);  NativeCP = __GetDefaultCP(ltype->lc.id);  /* Make table with all characters. */  for (i = 0; i < 256; ++i) Buffer[i] = (unsigned char)i;  if (!GetCPInfo(NativeCP, &CPInfo)) { free(ltype); return NULL; }  if (CPInfo.MaxCharSize > 1) {    for (ptr = (unsigned char*)CPInfo.LeadByte; *ptr && *(ptr + 1); ptr+=2)      for (i = *ptr; i <= *(ptr + 1); ++i) Buffer[i] = 0;  }  if ((UINT)NativeCP != ltype->cp) {    OSVERSIONINFO ver_info;    ver_info.dwOSVersionInfoSize = sizeof(ver_info);    GetVersionEx(&ver_info);    if (ver_info.dwPlatformId == VER_PLATFORM_WIN32_NT) {      /* Convert character sequence to Unicode. */      BufferSize = MultiByteToWideChar(ltype->cp, MB_PRECOMPOSED, (const char*)Buffer, 256, NULL, 0);      if (!BufferSize) { free(ltype); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }      wbuffer = (wchar_t*)malloc(BufferSize * sizeof(wchar_t));      if (!wbuffer) { free(ltype); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }      MultiByteToWideChar(ltype->cp, MB_PRECOMPOSED, (const char*)Buffer, 256, wbuffer, BufferSize);      GetStringTypeW(CT_CTYPE1, wbuffer, 256, ltype->ctable);      MapCtypeMasks(ltype->ctable, ltype->ctable + 256);      free(wbuffer);    }    else {      unsigned short ctable[256];      unsigned char TargetBuffer[256];      GetStringTypeA(ltype->lc.id, CT_CTYPE1, (const char*)Buffer, 256, ctable);      /* Convert character sequence to target code page. */      BufferSize = MultiByteToWideChar(NativeCP, MB_PRECOMPOSED, (const char*)Buffer, 256, NULL, 0);      if (!BufferSize) { free(ltype); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }      wbuffer = (wchar_t*)malloc(BufferSize * sizeof(wchar_t));      if (!wbuffer) { free(ltype); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }      MultiByteToWideChar(NativeCP, MB_PRECOMPOSED, (const char*)Buffer, 256, wbuffer, BufferSize);      if (!WideCharToMultiByte(ltype->cp, WC_COMPOSITECHECK | WC_SEPCHARS, wbuffer, BufferSize, (char*)TargetBuffer, 256, NULL, FALSE))      { free(wbuffer); free(ltype); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }      free(wbuffer);      /* Translate ctype table. */      for (i = 0; i < 256; ++i) {        if (!TargetBuffer[i]) continue;        ltype->ctable[TargetBuffer[i]] = MapCtypeMask(ctable[i]);      }    }  }  else {    GetStringTypeA(ltype->lc.id, CT_CTYPE1, (const char*)Buffer, 256, ltype->ctable);    MapCtypeMasks(ltype->ctable, ltype->ctable + 256);  }  return ltype;}_Locale_numeric_t* _Locale_numeric_create(const char * name, _Locale_lcid_t* lc_hint, int *__err_code) {  wchar_t wbuf[4];  char *GroupingBuffer;  int BufferSize;  _Locale_numeric_t *lnum = (_Locale_numeric_t*)malloc(sizeof(_Locale_numeric_t));  if (!lnum) { *__err_code = _STLP_LOC_NO_MEMORY; return lnum; }  memset(lnum, 0, sizeof(_Locale_numeric_t));  if (__GetLCIDFromName(name, &lnum->lc.id, lnum->cp, lc_hint) == -1)  { free(lnum); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }#if defined (__BORLANDC__)  if (lnum->lc.id != INVARIANT_LCID) {#endif  __GetLocaleInfoUsingACP(lnum->lc.id, lnum->cp, LOCALE_SDECIMAL, lnum->decimal_point, 4, wbuf, 4);  __GetLocaleInfoUsingACP(lnum->lc.id, lnum->cp, LOCALE_STHOUSAND, lnum->thousands_sep, 4, wbuf, 4);#if defined (__BORLANDC__)  }  else    lnum->decimal_point[0] = '.';#endif  if (lnum->lc.id != INVARIANT_LCID) {    BufferSize = GetLocaleInfoA(lnum->lc.id, LOCALE_SGROUPING, NULL, 0);    GroupingBuffer = (char*)malloc(BufferSize);    if (!GroupingBuffer) { free(lnum); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }    GetLocaleInfoA(lnum->lc.id, LOCALE_SGROUPING, GroupingBuffer, BufferSize);    __FixGrouping(GroupingBuffer);    lnum->grouping = GroupingBuffer;  }  else {    lnum->grouping = (char*)malloc(1);    if (!lnum->grouping) { free(lnum); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }    lnum->grouping[0] = 0;  }  return lnum;}static int __ConvertDate(const char *NTDate, char *buffer, int buf_size) {  /* This function will return an incomplete buffer if buffer is not long enough */  const char *cur_char;  char *cur_output, *end_output;  /* Correct time format. */  cur_char = NTDate;  cur_output = buffer;  end_output = cur_output + buf_size;  buf_size = 0;  while (*cur_char) {    if (cur_output && (cur_output == end_output)) break;    switch (*cur_char) {    case 'd':    {      if (*(cur_char + 1) == 'd') {        if (cur_output && (cur_output + 2 > end_output)) {          *cur_output = 0;          return ++buf_size;        }        if (*(cur_char + 2) == 'd') {

⌨️ 快捷键说明

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