1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4// ============================================================
5//
6// FusionHelpers.cpp
7//
8// Implements various helper functions
9//
10// ============================================================
11
12#include "fusionhelpers.hpp"
13
14#include "shlwapi.h"
15
16#define IS_UPPER_A_TO_Z(x) (((x) >= L'A') && ((x) <= L'Z'))
17#define IS_LOWER_A_TO_Z(x) (((x) >= L'a') && ((x) <= L'z'))
18#define IS_0_TO_9(x) (((x) >= L'0') && ((x) <= L'9'))
19#define CAN_SIMPLE_UPCASE(x) (((x)&~0x7f) == 0)
20#define SIMPLE_UPCASE(x) (IS_LOWER_A_TO_Z(x) ? ((x) - L'a' + L'A') : (x))
21#define CAN_SIMPLE_LOWERCASE(x) (((x)&~0x7f) == 0)
22#define SIMPLE_LOWERCASE(x) (IS_UPPER_A_TO_Z(x) ? ((x) - L'A' + L'a') : (x))
23
24// ---------------------------------------------------------------------------
25// Private Helpers
26// ---------------------------------------------------------------------------
27namespace
28{
29 WCHAR FusionMapChar(WCHAR wc)
30 {
31 WCHAR wTmp;
32
33#ifndef FEATURE_PAL
34
35#ifdef FEATURE_USE_LCID
36 int iRet = WszLCMapString(g_lcid, LCMAP_UPPERCASE, &wc, 1, &wTmp, 1);
37#else
38 int iRet = LCMapStringEx(g_lcid, LCMAP_UPPERCASE, &wc, 1, &wTmp, 1, NULL, NULL, 0);
39#endif
40 if (!iRet) {
41 _ASSERTE(!"LCMapString failed!");
42 iRet = GetLastError();
43 wTmp = wc;
44 }
45#else // !FEATURE_PAL
46 // For PAL, no locale specific processing is done
47 wTmp = toupper(wc);
48#endif // !FEATURE_PAL
49
50 return wTmp;
51 }
52};
53
54// ---------------------------------------------------------------------------
55// FusionCompareStringN
56// ---------------------------------------------------------------------------
57// if nChar < 0, compare the whole string
58int FusionCompareStringN(LPCWSTR pwz1, LPCWSTR pwz2, int nChar, BOOL bCaseSensitive)
59{
60 int iRet = 0;
61 int nCount = 0;
62 WCHAR ch1;
63 WCHAR ch2;
64 _ASSERTE(pwz1 && pwz2);
65
66 // same point always return equal.
67 if (pwz1 == pwz2) {
68 return 0;
69 }
70
71 // Case sensitive comparison
72 if (bCaseSensitive) {
73 if (nChar >= 0)
74 return wcsncmp(pwz1, pwz2, nChar);
75 else
76 return wcscmp(pwz1, pwz2);
77 }
78
79 for (;;) {
80 ch1 = *pwz1++;
81 ch2 = *pwz2++;
82
83 if (ch1 == L'\0' || ch2 == L'\0') {
84 break;
85 }
86
87 // We use OS mapping table
88 ch1 = (CAN_SIMPLE_UPCASE(ch1)) ? (SIMPLE_UPCASE(ch1)) : (FusionMapChar(ch1));
89 ch2 = (CAN_SIMPLE_UPCASE(ch2)) ? (SIMPLE_UPCASE(ch2)) : (FusionMapChar(ch2));
90 nCount++;
91
92 if (ch1 != ch2 || (nChar >= 0 && nCount >= nChar)) {
93 break;
94 }
95 }
96
97 if (ch1 > ch2) {
98 iRet = 1;
99 }
100 else if (ch1 < ch2) {
101 iRet = -1;
102 }
103
104 return iRet;
105}
106
107// ---------------------------------------------------------------------------
108// FusionCompareStringI
109// ---------------------------------------------------------------------------
110int FusionCompareStringI(LPCWSTR pwz1, LPCWSTR pwz2)
111{
112 return FusionCompareStringN(pwz1, pwz2, -1, FALSE);
113}
114