size_t _Locale_strxfrm(struct _Locale_collate* lcol, char* dst, size_t dst_size, const char* src, size_t src_size) { if(__GetDefaultCP(lcol->lcid) == atoi(lcol->cp)) return LCMapStringA(lcol->lcid, LCMAP_SORTKEY, src, src_size, dst, dst_size); else { int result; char *buf; size_t size; buf = __ConvertToCP(atoi(lcol->cp), __GetDefaultCP(lcol->lcid), src, src_size, &size); result=LCMapStringA(lcol->lcid, LCMAP_SORTKEY, buf, size, dst, dst_size); free(buf); return result; } }
int _Locale_tolower(struct _Locale_ctype* ltype, int c) { char buf[2], out_buf[2]; buf[0] = (char)c; buf[1] = 0; if(__GetDefaultCP(ltype->lcid) == ltype->cp) { LCMapStringA(ltype->lcid, LCMAP_LINGUISTIC_CASING | LCMAP_LOWERCASE, buf, 2, out_buf, 2); return out_buf[0]; } else { wchar_t wbuf[2]; MultiByteToWideChar(ltype->cp, MB_PRECOMPOSED, buf, 2, wbuf, 2); WideCharToMultiByte(__GetDefaultCP(ltype->lcid), WC_COMPOSITECHECK | WC_SEPCHARS, wbuf, 2, buf, 2, NULL, FALSE); LCMapStringA(ltype->lcid, LCMAP_LINGUISTIC_CASING | LCMAP_LOWERCASE, buf, 2, out_buf, 2); MultiByteToWideChar(__GetDefaultCP(ltype->lcid), MB_PRECOMPOSED, out_buf, 2, wbuf, 2); WideCharToMultiByte(ltype->cp, WC_COMPOSITECHECK | WC_SEPCHARS, wbuf, 2, out_buf, 2, NULL, FALSE); return out_buf[0]; } }
size_t strxfrm( char *dest, const char *src, size_t n ) { int ret = LCMapStringA(LOCALE_USER_DEFAULT,LCMAP_LOWERCASE, src, strlen(src), dest, strlen(dest)); if ( ret == 0 ) return -1; return ret; }
size_t CDECL _strxfrm_l( char *dest, const char *src, size_t len, _locale_t locale ) { MSVCRT_pthreadlocinfo locinfo; int ret; if(!MSVCRT_CHECK_PMT(src)) return INT_MAX; if(!MSVCRT_CHECK_PMT(dest || !len)) return INT_MAX; if(len > INT_MAX) { FIXME("len > INT_MAX not supported\n"); len = INT_MAX; } if(!locale) locinfo = get_locinfo(); else locinfo = ((MSVCRT__locale_t)locale)->locinfo; if(!locinfo->lc_handle[MSVCRT_LC_COLLATE]) { strncpy(dest, src, len); return strlen(src); } ret = LCMapStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE], LCMAP_SORTKEY, src, -1, NULL, 0); if(!ret) { if(len) dest[0] = 0; *_errno() = EILSEQ; return INT_MAX; } if(!len) return ret-1; if(ret > len) { dest[0] = 0; *_errno() = ERANGE; return ret-1; } return LCMapStringA(locinfo->lc_handle[MSVCRT_LC_COLLATE], LCMAP_SORTKEY, src, -1, dest, len) - 1; }
/********************************************************************* * __crtLCMapStringA (MSVCRT.@) */ int CDECL __crtLCMapStringA( LCID lcid, DWORD mapflags, const char* src, int srclen, char* dst, int dstlen, unsigned int codepage, int xflag ) { FIXME("(lcid %x, flags %x, %s(%d), %p(%d), %x, %d), partial stub!\n", lcid,mapflags,src,srclen,dst,dstlen,codepage,xflag); /* FIXME: A bit incorrect. But msvcrt itself just converts its * arguments to wide strings and then calls LCMapStringW */ return LCMapStringA(lcid,mapflags,src,srclen,dst,dstlen); }
/****************************************************************************** * LCMapStringA [OLE2NLS.6] */ INT16 WINAPI LCMapString16(LCID lcid, DWORD mapflags, LPCSTR srcstr, INT16 srclen, LPSTR dststr, INT16 dstlen) { return LCMapStringA(lcid, mapflags, srcstr, srclen, dststr, dstlen); }
static int __cdecl __crtLCMapStringW_stat( _locale_t plocinfo, LCID Locale, DWORD dwMapFlags, LPCWSTR lpSrcStr, int cchSrc, LPWSTR lpDestStr, int cchDest, int code_page ) { static int f_use = 0; /* * Look for unstubbed 'preferred' flavor. Otherwise use available flavor. * Must actually call the function to ensure it's not a stub. */ if (0 == f_use) { if (0 != LCMapStringW(0, LCMAP_LOWERCASE, L"\0", 1, NULL, 0)) { f_use = USE_W; } else if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { f_use = USE_A; } } /* * LCMapString will map past NULL. Must find NULL if in string * before cchSrc wide characters. */ if (cchSrc > 0) { cchSrc = wcsncnt(lpSrcStr, cchSrc); } /* Use "W" version */ if (USE_W == f_use) { return LCMapStringW(Locale, dwMapFlags, lpSrcStr, cchSrc, lpDestStr, cchDest); } /* Use "A" version */ if (USE_A == f_use || f_use == 0) { int retval = 0; int inbuff_size; int outbuff_size; unsigned char* inbuffer = NULL; unsigned char* outbuffer = NULL; int AnsiCP = 0; /* * Convert string and return the requested information. Note that * we are converting to a multibyte string so there is not a * one-to-one correspondence between number of wide chars in the * input string and the number of *bytes* in the buffer. However, * there had *better be* a one-to-one correspondence between the * number of wide characters and the number of multibyte characters * (enforced by WC_SEPCHARS) in the buffer or the resulting mapped * string will be worthless to the user. * */ /* * Use __lc_codepage for conversion if code_page not specified */ if (0 == Locale) { Locale = plocinfo->locinfo->lc_handle[LC_CTYPE]; } if (0 == code_page) { code_page = plocinfo->locinfo->lc_codepage; } /* * Always use Ansi codepage with Ansi WinAPI because they use * Ansi codepage */ if (code_page != (AnsiCP = __ansicp(Locale))) { if (AnsiCP != -1) { code_page = AnsiCP; } } /* find out how big a buffer we need (includes NULL if any) */ if (0 == (inbuff_size = WideCharToMultiByte(code_page, 0, lpSrcStr, cchSrc, NULL, 0, NULL, NULL))) { return 0; } /* allocate enough space for chars */ inbuffer = (unsigned char*)_calloca(inbuff_size, sizeof(char)); if (inbuffer == NULL) { return 0; } /* do the conversion */ if (0 == WideCharToMultiByte(code_page, 0, lpSrcStr, cchSrc, (char*)inbuffer, inbuff_size, NULL, NULL)) { goto error_cleanup; } /* get size required for string mapping */ if (0 == (outbuff_size = LCMapStringA(Locale, dwMapFlags, (const char*)inbuffer, inbuff_size, NULL, 0))) { goto error_cleanup; } /* allocate enough space for chars and NULL */ outbuffer = (unsigned char*)_calloca(outbuff_size, sizeof(char)); if (outbuffer == NULL) { goto error_cleanup; } /* do string mapping */ if (0 == LCMapStringA(Locale, dwMapFlags, (const char*)inbuffer, inbuff_size, (char*)outbuffer, outbuff_size)) { goto error_cleanup; } if (dwMapFlags & LCMAP_SORTKEY) { /* outbuff_size > cchDest is allowed */ retval = outbuff_size; if (0 != cchDest) /* SORTKEY returns BYTES, just copy */ _ERRCHECK(strncpy_s((char*)lpDestStr, cchDest, (char*)outbuffer, cchDest <= outbuff_size ? cchDest - 1 : outbuff_size)); } else { if (0 == cchDest) { /* get size required */ if (0 == (retval = MultiByteToWideChar(code_page, MB_PRECOMPOSED, (const char*)outbuffer, outbuff_size, NULL, 0))) { goto error_cleanup; } } else { /* convert mapping */ if (0 == (retval = MultiByteToWideChar(code_page, MB_PRECOMPOSED, (const char*)outbuffer, outbuff_size, lpDestStr, cchDest))) { goto error_cleanup; } } } error_cleanup: if (outbuffer != NULL) { _freea(outbuffer); } _freea(inbuffer); return retval; } else { /* f_use is neither USE_A nor USE_W */ return 0; } }
int __cdecl __crtLCMapStringA( LCID Locale, DWORD dwMapFlags, LPCSTR lpSrcStr, int cchSrc, LPSTR lpDestStr, int cchDest, int code_page, BOOL bError ) { static int f_use = 0; /* * Look for unstubbed 'preferred' flavor. Otherwise use available flavor. * Must actually call the function to ensure it's not a stub. * (Always try wide version first so WinNT can process codepage correctly.) */ if (0 == f_use) { if (0 != LCMapStringW(0, LCMAP_LOWERCASE, L"\0", 1, NULL, 0)) f_use = USE_W; else if (0 != LCMapStringA(0, LCMAP_LOWERCASE, "\0", 1, NULL, 0)) f_use = USE_A; else return 0; } /* * LCMapString will map past NULL. Must find NULL if in string * before cchSrc characters. */ if (cchSrc > 0) cchSrc = strncnt(lpSrcStr, cchSrc); /* Use "A" version */ if (USE_A == f_use) { return LCMapStringA( Locale, dwMapFlags, lpSrcStr, cchSrc, lpDestStr, cchDest ); } /* Use "W" version */ if (USE_W == f_use) { int retval; int inbuff_size; int outbuff_size; wchar_t *inwbuffer; wchar_t *outwbuffer; /* * Convert string and return the requested information. Note that * we are converting to a wide string so there is not a * one-to-one correspondence between number of wide chars in the * input string and the number of *bytes* in the buffer. However, * there had *better be* a one-to-one correspondence between the * number of wide characters and the number of multibyte characters * or the resulting mapped string will be worthless to the user. */ /* * Use __lc_codepage for conversion if code_page not specified */ if (0 == code_page) code_page = __lc_codepage; /* find out how big a buffer we need (includes NULL if any) */ if ( 0 == (inbuff_size = MultiByteToWideChar( code_page, bError ? MB_PRECOMPOSED | MB_ERR_INVALID_CHARS : MB_PRECOMPOSED, lpSrcStr, cchSrc, NULL, 0 )) ) return 0; /* allocate enough space for wide chars */ __try { inwbuffer = (wchar_t *)_alloca( inbuff_size * sizeof(wchar_t) ); } __except(EXCEPTION_EXECUTE_HANDLER) { inwbuffer = NULL; } if ( inwbuffer == NULL ) return 0; /* do the conversion */ if ( 0 == MultiByteToWideChar( code_page, MB_PRECOMPOSED, lpSrcStr, cchSrc, inwbuffer, inbuff_size) ) return 0; /* get size required for string mapping */ if ( 0 == (retval = LCMapStringW( Locale, dwMapFlags, inwbuffer, inbuff_size, NULL, 0 )) ) return 0; if (dwMapFlags & LCMAP_SORTKEY) { /* retval is size in BYTES */ if (0 != cchDest) { if (retval > cchDest) return 0; /* do string mapping */ if ( 0 == LCMapStringW( Locale, dwMapFlags, inwbuffer, inbuff_size, (LPWSTR)lpDestStr, cchDest ) ) return 0; } } else { /* retval is size in wide chars */ outbuff_size = retval; /* allocate enough space for wide chars (includes NULL if any) */ __try { outwbuffer = (wchar_t *)_alloca( outbuff_size * sizeof(wchar_t) ); } __except(EXCEPTION_EXECUTE_HANDLER) { outwbuffer = NULL; } if ( outwbuffer == NULL ) return 0; /* do string mapping */ if ( 0 == LCMapStringW( Locale, dwMapFlags, inwbuffer, inbuff_size, outwbuffer, outbuff_size ) ) return 0; if (0 == cchDest) { /* get size required */ if ( 0 == (retval = WideCharToMultiByte( code_page, WC_COMPOSITECHECK | WC_SEPCHARS, outwbuffer, outbuff_size, NULL, 0, NULL, NULL )) ) return 0; } else { /* convert mapping */ if ( 0 == (retval = WideCharToMultiByte( code_page, WC_COMPOSITECHECK | WC_SEPCHARS, outwbuffer, outbuff_size, lpDestStr, cchDest, NULL, NULL )) ) return 0; } } return retval; }
int __cdecl __crtLCMapStringW( LCID Locale, DWORD dwMapFlags, LPCWSTR lpSrcStr, int cchSrc, LPWSTR lpDestStr, int cchDest, int code_page ) { static int f_use = 0; /* * Look for unstubbed 'preferred' flavor. Otherwise use available flavor. * Must actually call the function to ensure it's not a stub. */ if (0 == f_use) { if (0 != LCMapStringW(0, LCMAP_LOWERCASE, L"\0", 1, NULL, 0)) f_use = USE_W; else if (0 != LCMapStringA(0, LCMAP_LOWERCASE, "\0", 1, NULL, 0)) f_use = USE_A; else return 0; } /* * LCMapString will map past NULL. Must find NULL if in string * before cchSrc wide characters. */ if (cchSrc > 0) cchSrc = wcsncnt(lpSrcStr, cchSrc); /* Use "W" version */ if (USE_W == f_use) { return LCMapStringW( Locale, dwMapFlags, lpSrcStr, cchSrc, lpDestStr, cchDest ); } /* Use "A" version */ if (USE_A == f_use) { int retval; int inbuff_size; int outbuff_size; unsigned char *inbuffer; unsigned char *outbuffer; /* * Convert string and return the requested information. Note that * we are converting to a multibyte string so there is not a * one-to-one correspondence between number of wide chars in the * input string and the number of *bytes* in the buffer. However, * there had *better be* a one-to-one correspondence between the * number of wide characters and the number of multibyte characters * (enforced by WC_SEPCHARS) in the buffer or the resulting mapped * string will be worthless to the user. * */ /* * Use __lc_codepage for conversion if code_page not specified */ if (0 == code_page) code_page = __lc_codepage; /* find out how big a buffer we need (includes NULL if any) */ if ( 0 == (inbuff_size = WideCharToMultiByte( code_page, WC_COMPOSITECHECK | WC_SEPCHARS, lpSrcStr, cchSrc, NULL, 0, NULL, NULL )) ) return 0; /* allocate enough space for chars */ __try { inbuffer = (unsigned char *)_alloca( inbuff_size * sizeof(char) ); } __except(EXCEPTION_EXECUTE_HANDLER) { inbuffer = NULL; } if ( inbuffer == NULL ) return 0; /* do the conversion */ if ( 0 == WideCharToMultiByte( code_page, WC_COMPOSITECHECK | WC_SEPCHARS, lpSrcStr, cchSrc, inbuffer, inbuff_size, NULL, NULL ) ) return 0; /* get size required for string mapping */ if ( 0 == (outbuff_size = LCMapStringA( Locale, dwMapFlags, inbuffer, inbuff_size, NULL, 0 )) ) return 0; /* allocate enough space for chars and NULL */ __try { outbuffer = (unsigned char *)_alloca( outbuff_size * sizeof(char) ); } __except(EXCEPTION_EXECUTE_HANDLER) { outbuffer = NULL; } if ( outbuffer == NULL ) return 0; /* do string mapping */ if ( 0 == LCMapStringA( Locale, dwMapFlags, inbuffer, inbuff_size, outbuffer, outbuff_size ) ) return 0; if (dwMapFlags & LCMAP_SORTKEY) { /* outbuff_size > cchDest is allowed */ retval = outbuff_size; if (0 != cchDest) /* SORTKEY returns BYTES, just copy */ strncpy( (char *)lpDestStr, (char *)outbuffer, cchDest < outbuff_size ? cchDest : outbuff_size ); } else { if (0 == cchDest) { /* get size required */ if ( 0 == (retval = MultiByteToWideChar( code_page, MB_PRECOMPOSED, outbuffer, outbuff_size, NULL, 0 )) ) return 0; } else { /* convert mapping */ if ( 0 == (retval = MultiByteToWideChar( code_page, MB_PRECOMPOSED, outbuffer, outbuff_size, lpDestStr, cchDest )) ) return 0; } } return retval; }