/*** *inithelp.c - Contains the __getlocaleinfo helper routine * * Copyright (c) 1992-1997, Microsoft Corporation. All rights reserved. * *Purpose: * Contains the __getlocaleinfo helper routine. * *******************************************************************************/ #include #include #include #include #include #include /*** *__getlocaleinfo - return locale data * *Purpose: * Return locale data appropriate for the setlocale init functions. * In particular, wide locale strings are converted to char strings * or numeric depending on the value of the first parameter. * * Memory is allocated for the char version of the data, and the * calling function's pointer is set to it. This pointer should later * be used to free the data. The wide-char data is fetched using * GetLocaleInfo and converted to multibyte using WideCharToMultiByte. * * *** For internal use by the __init_* functions only *** * * *** Future optimization *** * When converting a large number of wide-strings to multibyte, do * not query the size of the result, but convert them one after * another into a large character buffer. The entire buffer can * also be freed with one pointer. * *Entry: * int lc_type - LC_STR_TYPE for string data, LC_INT_TYPE for numeric data * LCID localehandle - LCID based on category and lang or ctry of __lc_id * LCTYPE fieldtype - int or string value * void *address - cast to either char * or char** * *Exit: * 0 success * -1 failure * *Exceptions: * *******************************************************************************/ #if NO_ERROR == -1 #error Need to use another error return code in __getlocaleinfo #endif /* NO_ERROR == -1 */ #define STR_CHAR_CNT 128 #define INT_CHAR_CNT 4 int __cdecl __getlocaleinfo ( int lc_type, LCID localehandle, LCTYPE fieldtype, void *address ) { if (lc_type == LC_STR_TYPE) { char **straddress = (char **)address; unsigned char cbuffer[STR_CHAR_CNT]; unsigned char *pcbuffer = cbuffer; int bufferused = 0; /* 1 indicates buffer points to malloc'ed memory */ int buffersize = STR_CHAR_CNT; int outsize; if ((outsize = __crtGetLocaleInfoA(localehandle, fieldtype, pcbuffer, buffersize, 0)) == 0) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) goto error; /* buffersize too small, get required size and malloc new buffer */ if ((buffersize = __crtGetLocaleInfoA (localehandle, fieldtype, NULL, 0, 0)) == 0) goto error; if ((pcbuffer = (unsigned char *) _malloc_crt (buffersize * sizeof(unsigned char))) == NULL) goto error; bufferused = 1; if ((outsize = __crtGetLocaleInfoA (localehandle, fieldtype, pcbuffer, buffersize, 0)) == 0) goto error; } if ((*straddress = (char *) _malloc_crt (outsize * sizeof(char))) == NULL) goto error; strncpy(*straddress, pcbuffer, outsize); if (bufferused) _free_crt (pcbuffer); return 0; error: if (bufferused) _free_crt (pcbuffer); return -1; } else if (lc_type == LC_INT_TYPE) { int i; char c; static wchar_t wcbuffer[INT_CHAR_CNT]; const int buffersize = INT_CHAR_CNT; char *charaddress = (char *)address; if (__crtGetLocaleInfoW (localehandle, fieldtype, (LPWSTR)&wcbuffer, buffersize, 0) == 0) return -1; *(char *)charaddress = 0; /* assume GetLocaleInfoW returns valid ASCII integer in wcstr format */ for (i = 0; i < INT_CHAR_CNT; i++) { if (isdigit(((unsigned char)c = (unsigned char)wcbuffer[i]))) *(unsigned char *)charaddress = (unsigned char)(10 * (int)(*charaddress) + (c - '0')); else break; } return 0; } return -1; }