Reactos
at master 135 lines 4.4 kB view raw
1/*** 2*wcsxfrm.c - Transform a wide-character string using locale information 3* 4* Copyright (c) Microsoft Corporation. All rights reserved. 5* 6*Purpose: 7* Transform a wide-character string using the locale information as set by 8* LC_COLLATE. 9* 10*******************************************************************************/ 11#include <corecrt_internal.h> 12#include <ctype.h> 13#include <locale.h> 14#include <string.h> 15 16/*** 17*size_t wcsxfrm() - Transform a string using locale information 18* 19*Purpose: 20* Transform the wide string pointed to by _string2 and place the 21* resulting wide string into the array pointed to by _string1. 22* No more than _count wide characters are placed into the 23* resulting string (including the null). 24* 25* The transformation is such that if wcscmp() is applied to 26* the two transformed strings, the return value is equal to 27* the result of wcscoll() applied to the two original strings. 28* Thus, the conversion must take the locale LC_COLLATE info 29* into account. 30* 31* In the C locale, wcsxfrm() simply resolves to wcsncpy()/wcslen(). 32* 33*Entry: 34* wchar_t *_string1 = result string 35* const wchar_t *_string2 = source string 36* size_t _count = max wide chars to move 37* 38* [If _count is 0, _string1 is permitted to be nullptr.] 39* 40*Exit: 41* Length of the transformed string (not including the terminating 42* null). If the value returned is >= _count, the contents of the 43* _string1 array are indeterminate. 44* 45*Exceptions: 46* Non-standard: if OM/API error, return INT_MAX. 47* Input parameters are validated. Refer to the validation section of the function. 48* 49*******************************************************************************/ 50 51extern "C" size_t __cdecl _wcsxfrm_l ( 52 wchar_t *_string1, 53 const wchar_t *_string2, 54 size_t _count, 55 _locale_t plocinfo 56 ) 57{ 58 int size = INT_MAX; 59 60 /* validation section */ 61 _VALIDATE_RETURN(_count <= INT_MAX, EINVAL, INT_MAX); 62 _VALIDATE_RETURN(_string1 != nullptr || _count == 0, EINVAL, INT_MAX); 63 _VALIDATE_RETURN(_string2 != nullptr, EINVAL, INT_MAX); 64 65 _LocaleUpdate _loc_update(plocinfo); 66 67 if ( _loc_update.GetLocaleT()->locinfo->locale_name[LC_COLLATE] == nullptr ) 68 { 69_BEGIN_SECURE_CRT_DEPRECATION_DISABLE 70 wcsncpy(_string1, _string2, _count); 71_END_SECURE_CRT_DEPRECATION_DISABLE 72 return wcslen(_string2); 73 } 74 75 if ( 0 == (size = __acrt_LCMapStringW( 76 _loc_update.GetLocaleT()->locinfo->locale_name[LC_COLLATE], 77 LCMAP_SORTKEY, 78 _string2, 79 -1, 80 nullptr, 81 0 )) ) 82 { 83 errno = EILSEQ; 84 size = INT_MAX; 85 } else 86 { 87 if ( size <= (int)_count) 88 { 89 if ( 0 == (size = __acrt_LCMapStringW( 90 _loc_update.GetLocaleT()->locinfo->locale_name[LC_COLLATE], 91 LCMAP_SORTKEY, 92 _string2, 93 -1, 94 (wchar_t *)_string1, 95 (int)_count )) ) 96 { 97 errno = EILSEQ; 98 size = INT_MAX; /* default error */ 99 } else 100 { 101 // Note that the size that LCMapStringW returns for 102 // LCMAP_SORTKEY is number of bytes needed. That's why it 103 // is safe to convert the buffer to wide char from end. 104 _count = size--; 105 for (;_count-- > 0;) 106 { 107#pragma warning(suppress:__WARNING_DEREF_NULL_PTR __WARNING_POTENTIAL_BUFFER_OVERFLOW_HIGH_PRIORITY) // 6011 Dereferencing NULL pointer '_string1' 26015 Potential overflow using expression '_string1[_count]' 108 _string1[_count] = (wchar_t)((unsigned char *)_string1)[_count]; 109 } 110 } 111 } 112 else 113 { 114 if (_string1 != nullptr && _count > 0) 115 { 116 *_string1 = '\0'; 117 errno = ERANGE; 118 } 119 size--; 120 } 121 } 122 123 return (size_t)size; 124} 125 126extern "C" size_t __cdecl wcsxfrm ( 127 wchar_t *_string1, 128 const wchar_t *_string2, 129 size_t _count 130 ) 131{ 132 133 return _wcsxfrm_l(_string1, _string2, _count, nullptr); 134} 135