-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
Copy pathxstrxfrm.cpp
96 lines (84 loc) · 3.33 KB
/
xstrxfrm.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// Transform a string using the locale information as set by LC_COLLATE.
#include <__msvc_xlocinfo_types.hpp>
#include <clocale>
#include <cstdlib>
#include <cstring>
#include <malloc.h>
#include <Windows.h>
#include "awint.hpp"
_EXTERN_C_UNLESS_PURE
// size_t _Strxfrm() - Transform a string using locale information
//
// Purpose:
// Transform the string pointed to by string2 and place the
// resulting string into the array pointed to by string1.
// No more than end1 - string1 characters are placed into the
// resulting string (including the null).
//
// The transformation is such that if strcmp() is applied to
// the two transformed strings, the return value is equal to
// the result of strcoll() applied to the two original strings.
// Thus, the conversion must take the locale LC_COLLATE info
// into account.
// [ANSI]
//
// The value of the following expression is the size of the array
// needed to hold the transformation of the source string:
//
// 1 + strxfrm(nullptr,string,0)
//
// In the "C" locale, _Strxfrm() simply resolves to strncpy()/strlen().
//
// Entry:
// char* string1 = pointer to beginning of result string
// char* end1 = pointer past end of result string
// const char* string2 = pointer to beginning of source string
// const char* 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.
_CRTIMP2_PURE size_t __CLRCALL_PURE_OR_CDECL _Strxfrm(_Out_writes_(end1 - string1)
_Post_readable_size_(return) char* string1,
_In_z_ char* end1, const char* string2, const char* end2, const _Collvec* ploc) noexcept {
size_t n1 = end1 - string1;
size_t n2 = end2 - string2;
size_t retval = static_cast<size_t>(-1); // NON-ANSI: default if OM or API error
UINT codepage;
const wchar_t* locale_name;
if (ploc == nullptr) {
locale_name = ___lc_locale_name_func()[LC_COLLATE];
codepage = ___lc_collate_cp_func();
} else {
locale_name = ploc->_LocaleName;
codepage = ploc->_Page;
}
if (locale_name == nullptr && codepage == CP_ACP) {
if (n2 <= n1) {
memcpy(string1, string2, n2);
}
retval = n2;
} else {
// Inquire size of dst string in BYTES
const int dstlen =
__crtLCMapStringA(locale_name, LCMAP_SORTKEY, string2, static_cast<int>(n2), nullptr, 0, codepage, TRUE);
if (dstlen != 0) {
retval = dstlen;
// if not enough room, return amount needed
if (dstlen <= static_cast<int>(n1)) {
// Map src string to dst string
__crtLCMapStringA(locale_name, LCMAP_SORTKEY, string2, static_cast<int>(n2), string1,
static_cast<int>(n1), codepage, TRUE);
}
}
}
return retval;
}
_END_EXTERN_C_UNLESS_PURE