1 // Common/String.cpp
2 
3 #include "StdAfx.h"
4 
5 #ifdef _WIN32
6 #include "StringConvert.h"
7 #else
8 #include <ctype.h>
9 #endif
10 
11 #include "Common/String.h"
12 
13 
14 #ifdef _WIN32
15 
16 #ifndef _UNICODE
17 
MyCharUpper(wchar_t c)18 wchar_t MyCharUpper(wchar_t c)
19 {
20   if (c == 0)
21     return 0;
22   wchar_t *res = CharUpperW((LPWSTR)(unsigned int)c);
23   if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
24     return (wchar_t)(unsigned int)res;
25   const int kBufferSize = 4;
26   char s[kBufferSize + 1];
27   int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0);
28   if (numChars == 0 || numChars > kBufferSize)
29     return c;
30   s[numChars] = 0;
31   ::CharUpperA(s);
32   ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);
33   return c;
34 }
35 
MyCharLower(wchar_t c)36 wchar_t MyCharLower(wchar_t c)
37 {
38   if (c == 0)
39     return 0;
40   wchar_t *res = CharLowerW((LPWSTR)(unsigned int)c);
41   if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
42     return (wchar_t)(unsigned int)res;
43   const int kBufferSize = 4;
44   char s[kBufferSize + 1];
45   int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0);
46   if (numChars == 0 || numChars > kBufferSize)
47     return c;
48   s[numChars] = 0;
49   ::CharLowerA(s);
50   ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);
51   return c;
52 }
53 
MyStringUpper(wchar_t * s)54 wchar_t * MyStringUpper(wchar_t *s)
55 {
56   if (s == 0)
57     return 0;
58   wchar_t *res = CharUpperW(s);
59   if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
60     return res;
61   AString a = UnicodeStringToMultiByte(s);
62   a.MakeUpper();
63   return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));
64 }
65 
MyStringLower(wchar_t * s)66 wchar_t * MyStringLower(wchar_t *s)
67 {
68   if (s == 0)
69     return 0;
70   wchar_t *res = CharLowerW(s);
71   if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
72     return res;
73   AString a = UnicodeStringToMultiByte(s);
74   a.MakeLower();
75   return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));
76 }
77 
78 #endif
79 
80 /*
81 inline int ConvertCompareResult(int r) { return r - 2; }
82 
83 int MyStringCollate(const wchar_t *s1, const wchar_t *s2)
84 {
85   int res = CompareStringW(
86         LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1);
87   #ifdef _UNICODE
88   return ConvertCompareResult(res);
89   #else
90   if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
91     return ConvertCompareResult(res);
92   return MyStringCollate(UnicodeStringToMultiByte(s1),
93         UnicodeStringToMultiByte(s2));
94   #endif
95 }
96 
97 #ifndef _WIN32_WCE
98 int MyStringCollate(const char *s1, const char *s2)
99 {
100   return ConvertCompareResult(CompareStringA(
101     LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1));
102 }
103 
104 int MyStringCollateNoCase(const char *s1, const char *s2)
105 {
106   return ConvertCompareResult(CompareStringA(
107     LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1));
108 }
109 #endif
110 
111 int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2)
112 {
113   int res = CompareStringW(
114         LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1);
115   #ifdef _UNICODE
116   return ConvertCompareResult(res);
117   #else
118   if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
119     return ConvertCompareResult(res);
120   return MyStringCollateNoCase(UnicodeStringToMultiByte(s1),
121       UnicodeStringToMultiByte(s2));
122   #endif
123 }
124 */
125 
126 #else
127 
MyCharUpper(wchar_t c)128 wchar_t MyCharUpper(wchar_t c)
129 {
130   return toupper(c);
131 }
132 
133 /*
134 int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2)
135 {
136   while (true)
137   {
138     wchar_t c1 = *s1++;
139     wchar_t c2 = *s2++;
140     wchar_t u1 = MyCharUpper(c1);
141     wchar_t u2 = MyCharUpper(c2);
142 
143     if (u1 < u2) return -1;
144     if (u1 > u2) return 1;
145     if (u1 == 0) return 0;
146   }
147 }
148 */
149 
150 #endif
151 
MyStringCompare(const char * s1,const char * s2)152 int MyStringCompare(const char *s1, const char *s2)
153 {
154   while (true)
155   {
156     unsigned char c1 = (unsigned char)*s1++;
157     unsigned char c2 = (unsigned char)*s2++;
158     if (c1 < c2) return -1;
159     if (c1 > c2) return 1;
160     if (c1 == 0) return 0;
161   }
162 }
163 
MyStringCompare(const wchar_t * s1,const wchar_t * s2)164 int MyStringCompare(const wchar_t *s1, const wchar_t *s2)
165 {
166   while (true)
167   {
168     wchar_t c1 = *s1++;
169     wchar_t c2 = *s2++;
170     if (c1 < c2) return -1;
171     if (c1 > c2) return 1;
172     if (c1 == 0) return 0;
173   }
174 }
175 
MyStringCompareNoCase(const wchar_t * s1,const wchar_t * s2)176 int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2)
177 {
178   while (true)
179   {
180     wchar_t c1 = *s1++;
181     wchar_t c2 = *s2++;
182     if (c1 != c2)
183     {
184       wchar_t u1 = MyCharUpper(c1);
185       wchar_t u2 = MyCharUpper(c2);
186       if (u1 < u2) return -1;
187       if (u1 > u2) return 1;
188     }
189     if (c1 == 0) return 0;
190   }
191 }
192 
193 #ifdef _WIN32
MyStringCompareNoCase(const char * s1,const char * s2)194 int MyStringCompareNoCase(const char *s1, const char *s2)
195 {
196   return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2));
197 }
198 #endif
199