143 lines
4.8 KiB
C
143 lines
4.8 KiB
C
|
/***
|
||
|
*xwcsxfrm.c - Transform a wide-character string using locale information
|
||
|
*
|
||
|
* Copyright (c) 1996-2001, Microsoft Corporation. All rights reserved.
|
||
|
*
|
||
|
*
|
||
|
*Purpose:
|
||
|
* Transform a wide-character string using the locale information as set by
|
||
|
* LC_COLLATE.
|
||
|
*
|
||
|
*Revision History:
|
||
|
* 01-XX-96 PJP Created from wcsxfrm.c January 1996 by P.J. Plauger
|
||
|
* 04-18-96 GJF Updated for current locale locking. Also, reformatted
|
||
|
* and made several cosmetic changes.
|
||
|
* 12-02-97 GJF Removed bogus codepage determination.
|
||
|
* 01-12-98 GJF Use _lc_collate_cp codepage.
|
||
|
* 01-05-99 GJF Changes for 64-bit size_t.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
|
||
|
#include <cruntime.h>
|
||
|
#include <windows.h>
|
||
|
#include <string.h>
|
||
|
#include <limits.h>
|
||
|
#include <locale.h>
|
||
|
#include <setlocal.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <mtdll.h>
|
||
|
#include <awint.h>
|
||
|
#include <dbgint.h>
|
||
|
#include <xlocinfo.h> /* for _Collvec, _Wcsxfrm */
|
||
|
|
||
|
/***
|
||
|
*size_t _Wcsxfrm() - Transform a string using locale information
|
||
|
*
|
||
|
*Purpose:
|
||
|
* Transform the wide string pointed to by _string2 and place the
|
||
|
* resulting wide string into the array pointed to by _string1.
|
||
|
* No more than _end1 - _string1 wide characters are placed into the
|
||
|
* resulting string (including the null).
|
||
|
*
|
||
|
* The transformation is such that if wcscmp() is applied to
|
||
|
* the two transformed strings, the return value is equal to
|
||
|
* the result of wcscoll() applied to the two original strings.
|
||
|
* Thus, the conversion must take the locale LC_COLLATE info
|
||
|
* into account.
|
||
|
*
|
||
|
* In the C locale, wcsxfrm() simply resolves to wcsncpy()/wcslen().
|
||
|
*
|
||
|
*Entry:
|
||
|
* wchar_t *_string1 = pointer to beginning of result string
|
||
|
* wchar_t *_end1 = pointer past end of result string
|
||
|
* const wchar_t *_string2 = pointer to beginning of source string
|
||
|
* const wchar_t *_end2 = pointer past end of source string
|
||
|
* const _Collvec *ploc = pointer to locale info
|
||
|
*
|
||
|
*Exit:
|
||
|
* Length of the transformed string.
|
||
|
* If the value returned is too big, the contents of the
|
||
|
* _string1 array are indeterminate.
|
||
|
*
|
||
|
*Exceptions:
|
||
|
* Non-standard: if OM/API error, return INT_MAX.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
size_t __cdecl _Wcsxfrm (
|
||
|
wchar_t *_string1,
|
||
|
wchar_t *_end1,
|
||
|
const wchar_t *_string2,
|
||
|
const wchar_t *_end2,
|
||
|
const _Collvec *ploc
|
||
|
)
|
||
|
{
|
||
|
size_t _n1 = _end1 - _string1;
|
||
|
size_t _n2 = _end2 - _string2;
|
||
|
int size = INT_MAX;
|
||
|
unsigned char *bbuffer;
|
||
|
LCID handle;
|
||
|
#ifdef _MT
|
||
|
int local_lock_flag;
|
||
|
|
||
|
_lock_locale( local_lock_flag )
|
||
|
#endif
|
||
|
|
||
|
if (ploc == 0)
|
||
|
handle = __lc_handle[LC_COLLATE];
|
||
|
else
|
||
|
handle = ploc->_Hand;
|
||
|
|
||
|
if (handle == _CLOCALEHANDLE) {
|
||
|
_unlock_locale( local_lock_flag )
|
||
|
if (_n2 <= _n1)
|
||
|
memcpy(_string1, _string2, _n2 * sizeof (wchar_t));
|
||
|
return _n2;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* When using LCMAP_SORTKEY, LCMapStringW handles BYTES not wide
|
||
|
* chars. We use a byte buffer to hold bytes and then convert the
|
||
|
* byte string to a wide char string and return this so it can be
|
||
|
* compared using wcscmp(). User's buffer is _n1 wide chars, so
|
||
|
* use an internal buffer of _n1 bytes.
|
||
|
*/
|
||
|
|
||
|
if (NULL == (bbuffer = (unsigned char *)_malloc_crt(_n1)))
|
||
|
goto error_cleanup;
|
||
|
|
||
|
if (0 == (size = __crtLCMapStringW(handle,
|
||
|
LCMAP_SORTKEY,
|
||
|
_string2,
|
||
|
(int)_n2,
|
||
|
(wchar_t *)bbuffer,
|
||
|
(int)_n1,
|
||
|
__lc_collate_cp)))
|
||
|
{
|
||
|
/* buffer not big enough, get size required. */
|
||
|
|
||
|
if (0 == (size = __crtLCMapStringW(handle,
|
||
|
LCMAP_SORTKEY,
|
||
|
_string2,
|
||
|
(int)_n2,
|
||
|
NULL,
|
||
|
0,
|
||
|
__lc_collate_cp)))
|
||
|
size = INT_MAX; /* default error */
|
||
|
|
||
|
} else {
|
||
|
int i;
|
||
|
/* string successfully mapped, convert to wide char */
|
||
|
|
||
|
for (i = 0; i < size; i++)
|
||
|
_string1[i] = (wchar_t)bbuffer[i];
|
||
|
}
|
||
|
|
||
|
error_cleanup:
|
||
|
_unlock_locale( local_lock_flag )
|
||
|
_free_crt(bbuffer);
|
||
|
|
||
|
return (size_t)size;
|
||
|
}
|