Reactos
at master 147 lines 4.5 kB view raw
1/*** 2*strxfrm.c - Transform a string using locale information 3* 4* Copyright (c) Microsoft Corporation. All rights reserved. 5* 6*Purpose: 7* Transform a 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 strxfrm() - Transform a string using locale information 18* 19*Purpose: 20* Transform the string pointed to by _string2 and place the 21* resulting string into the array pointed to by _string1. 22* No more than _count characters are place into the 23* resulting string (including the null). 24* 25* The transformation is such that if strcmp() is applied to 26* the two transformed strings, the return value is equal to 27* the result of strcoll() applied to the two original strings. 28* Thus, the conversion must take the locale LC_COLLATE info 29* into account. 30* [ANSI] 31* 32* The value of the following expression is the size of the array 33* needed to hold the transformation of the source string: 34* 35* 1 + strxfrm(nullptr,string,0) 36* 37*Entry: 38* char *_string1 = result string 39* const char *_string2 = source string 40* size_t _count = max chars to move 41* 42* [If _count is 0, _string1 is permitted to be nullptr.] 43* 44*Exit: 45* Length of the transformed string (not including the terminating 46* null). If the value returned is >= _count, the contents of the 47* _string1 array are indeterminate. 48* 49*Exceptions: 50* Non-standard: if OM/API error, return INT_MAX. 51* Input parameters are validated. Refer to the validation section of the function. 52* 53*******************************************************************************/ 54 55extern "C" size_t __cdecl _strxfrm_l ( 56 char *_string1, 57 const char *_string2, 58 size_t _count, 59 _locale_t plocinfo 60 ) 61{ 62 int dstlen; 63 size_t retval = INT_MAX; /* NON-ANSI: default if OM or API error */ 64 _LocaleUpdate _loc_update(plocinfo); 65 66 /* validation section */ 67 _VALIDATE_RETURN(_count <= INT_MAX, EINVAL, INT_MAX); 68 _VALIDATE_RETURN(_string1 != nullptr || _count == 0, EINVAL, INT_MAX); 69 _VALIDATE_RETURN(_string2 != nullptr, EINVAL, INT_MAX); 70 71 /* pre-init output in case of error */ 72 if(_string1!=nullptr && _count>0) 73 { 74 *_string1='\0'; 75 } 76 77 if ( (_loc_update.GetLocaleT()->locinfo->locale_name[LC_COLLATE] == nullptr) && 78 (_loc_update.GetLocaleT()->locinfo->lc_collate_cp == CP_ACP) ) 79 { 80_BEGIN_SECURE_CRT_DEPRECATION_DISABLE 81 strncpy(_string1, _string2, _count); 82_END_SECURE_CRT_DEPRECATION_DISABLE 83 return strlen(_string2); 84 } 85 86 /* Inquire size of dst string in BYTES */ 87 if ( 0 == (dstlen = __acrt_LCMapStringA( 88 _loc_update.GetLocaleT(), 89 _loc_update.GetLocaleT()->locinfo->locale_name[LC_COLLATE], 90 LCMAP_SORTKEY, 91 _string2, 92 -1, 93 nullptr, 94 0, 95 _loc_update.GetLocaleT()->locinfo->lc_collate_cp, 96 TRUE )) ) 97 { 98 errno = EILSEQ; 99 return INT_MAX; 100 } 101 102 retval = (size_t)dstlen; 103 104 /* if not enough room, return amount needed */ 105 if ( retval > _count ) 106 { 107 if (_string1 != nullptr && _count > 0) 108 { 109 *_string1 = '\0'; 110 errno = ERANGE; 111 } 112 /* the return value is the string length (without the terminating 0) */ 113 retval--; 114 return retval; 115 } 116 117 /* Map src string to dst string */ 118 if ( 0 == __acrt_LCMapStringA( 119 _loc_update.GetLocaleT(), 120 _loc_update.GetLocaleT()->locinfo->locale_name[LC_COLLATE], 121 LCMAP_SORTKEY, 122 _string2, 123 -1, 124 _string1, 125 (int)_count, 126 _loc_update.GetLocaleT()->locinfo->lc_collate_cp, 127 TRUE ) ) 128 { 129 errno = EILSEQ; 130 return INT_MAX; 131 } 132 /* the return value is the string length (without the terminating 0) */ 133 retval--; 134 135 return retval; 136} 137 138extern "C" size_t __cdecl strxfrm ( 139 char *_string1, 140 const char *_string2, 141 size_t _count 142 ) 143{ 144 145 return _strxfrm_l(_string1, _string2, _count, nullptr); 146 147}