Skip to content

Commit daa9ca4

Browse files
committed
Templated the 4 string functions for char types
1 parent f4001ff commit daa9ca4

File tree

1 file changed

+106
-63
lines changed

1 file changed

+106
-63
lines changed

Core/Libraries/Source/WWVegas/WWLib/stringex.h

Lines changed: 106 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include "bittype.h"
2222
#include <string.h>
23+
#include <ctype.h>
2324

2425

2526
// Declaration
@@ -55,6 +56,14 @@ template<size_t Size> size_t strlmove_t(char (&dst)[Size], const char *src);
5556
template<size_t Size> size_t strlmcat_t(char (&dst)[Size], const char *src);
5657
#endif
5758

59+
template<typename CharT> int strncmp_t(const CharT *str1, const CharT *str2, size_t maxcount);
60+
template<typename CharT> int strnicmp_t(const CharT* str1, const CharT* str2, size_t maxcount);
61+
62+
template<typename CharT> bool startsWith(const CharT *str, const CharT *prefix);
63+
template<typename CharT> bool startsWithNoCase(const CharT *str, const CharT *prefix);
64+
template<typename CharT> bool endsWithNoCase(const CharT *str, const CharT *suffix);
65+
template<typename CharT> bool endsWithNoCase(const CharT *str, const CharT *suffix);
66+
5867

5968
// Implementation
6069

@@ -183,106 +192,140 @@ template<size_t Size> size_t strlmove_t(char (&dst)[Size], const char *src) { re
183192
template<size_t Size> size_t strlmcat_t(char (&dst)[Size], const char *src) { return strlmcat_t(dst, src, Size); }
184193
#endif
185194

186-
inline bool startsWith(const char *str, const char *prefix)
195+
// Templated strncmp.
196+
// Compares up to maxcount chars or a null byte is encountered, whichever comes first.
197+
// Returns < 0 if str1 is less than str2, 0 is str1 and str2 are equal and > 0 if str2 is greater than str1.
198+
template<typename CharT> int strncmp_t(const CharT *str1, const CharT *str2, const size_t maxcount)
187199
{
188-
if (*prefix == char(0))
189-
return true; // everything starts with the empty string
200+
if (str1 == nullptr || str2 == nullptr)
201+
{
202+
switch (str1)
203+
{
204+
case str2:
205+
return 0;
206+
case nullptr:
207+
return -1;
208+
default:
209+
return 1;
210+
}
211+
}
212+
for (size_t i = 0; i < maxcount; ++i)
213+
{
214+
CharT c1 = str1[i];
215+
CharT c2 = str2[i];
216+
int diff = c1 - c2;
217+
if (diff != 0)
218+
{
219+
return diff;
220+
}
221+
if (c1 == CharT(0)) // both c1 and c2 are null terminators
222+
{
223+
return 0;
224+
}
225+
}
226+
return 0;
227+
}
190228

191-
const size_t strlen = ::strlen(str);
192-
const size_t prefixlen = ::strlen(prefix);
193-
if (strlen < prefixlen)
194-
return false; // prefix must be as long or shorter than str
229+
// Lower case conversion helpers
230+
inline char tolower_t(char c) {
231+
// cast to unsigned char for correct behavior of tolower()
232+
return (char)::tolower((unsigned char)c);
233+
}
195234

196-
return ::strncmp(str, prefix, prefixlen) == 0;
235+
inline wchar_t tolower_t(wchar_t c) {
236+
return (wchar_t)::towlower(c);
197237
}
198238

199-
inline bool startsWith(const wchar_t *str, const wchar_t *prefix)
239+
// Templated strnicmp.
240+
// Case insensitively compares up to maxcount chars or a null byte is encountered, whichever comes first.
241+
// Returns < 0 if str1 is less than str2, 0 is str1 and str2 are equal and > 0 if str2 is greater than str1.
242+
template<typename CharT> int strnicmp_t(const CharT *str1, const CharT *str2, const size_t maxcount)
200243
{
201-
if (*prefix == wchar_t(0))
202-
return true; // everything starts with the empty string
203-
204-
const size_t strlen = ::wcslen(str);
205-
const size_t prefixlen = ::wcslen(prefix);
206-
if (strlen < prefixlen)
207-
return false; // prefix must be as long or shorter than str
208-
209-
return ::wcsncmp(str, prefix, prefixlen) == 0;
244+
if (str1 == nullptr || str2 == nullptr)
245+
{
246+
switch (str1)
247+
{
248+
case str2:
249+
return 0;
250+
case nullptr:
251+
return -1;
252+
default:
253+
return 1;
254+
}
255+
}
256+
for (size_t i = 0; i < maxcount; ++i)
257+
{
258+
CharT c1 = tolower_t(str1[i]);
259+
CharT c2 = tolower_t(str2[i]);
260+
int diff = c1 - c2;
261+
if (diff != 0)
262+
{
263+
return diff;
264+
}
265+
if (c1 == CharT(0)) // both c1 and c2 are null terminators
266+
{
267+
return 0;
268+
}
269+
}
270+
return 0;
210271
}
211272

212-
inline bool startsWithNoCase(const char *str, const char *prefix)
273+
inline int strncmp_t(const char *str1, const char *str2, size_t maxcount) { return ::strncmp(str1, str2, maxcount); };
274+
inline int strncmp_t(const wchar_t *str1, const wchar_t *str2, size_t maxcount) { return ::wcsncmp(str1, str2, maxcount); };
275+
#ifdef _WIN32
276+
inline int strnicmp_t(const char *str1, const char *str2, size_t maxcount) { return ::_strnicmp(str1, str2, maxcount); };
277+
inline int strnicmp_t(const wchar_t *str1, const wchar_t *str2, size_t maxcount) { return ::_wcsnicmp(str1, str2, maxcount); };
278+
#endif
279+
280+
template<typename CharT> inline bool startsWith(const CharT *str, const CharT *prefix)
213281
{
214-
if (*prefix == char(0))
282+
if (*prefix == CharT(0))
215283
return true; // everything starts with the empty string
216284

217-
const size_t strlen = ::strlen(str);
218-
const size_t prefixlen = ::strlen(prefix);
285+
const size_t strlen = ::strlen_t(str);
286+
const size_t prefixlen = ::strlen_t(prefix);
219287
if (strlen < prefixlen)
220288
return false; // prefix must be as long or shorter than str
221289

222-
return ::strnicmp(str, prefix, prefixlen) == 0;
290+
return strncmp_t(str, prefix, prefixlen) == 0;
223291
}
224292

225-
inline bool startsWithNoCase(const wchar_t *str, const wchar_t *prefix)
293+
template<typename CharT> inline bool startsWithNoCase(const CharT *str, const CharT *prefix)
226294
{
227-
if (*prefix == wchar_t(0))
295+
if (*prefix == CharT(0))
228296
return true; // everything starts with the empty string
229297

230-
const size_t strlen = ::wcslen(str);
231-
const size_t prefixlen = ::wcslen(prefix);
298+
const size_t strlen = ::strlen_t(str);
299+
const size_t prefixlen = ::strlen_t(prefix);
232300
if (strlen < prefixlen)
233301
return false; // prefix must be as long or shorter than str
234302

235-
return ::wcsnicmp(str, prefix, prefixlen) == 0;
236-
}
237-
238-
inline bool endsWith(const char *str, const char *suffix)
239-
{
240-
if (*suffix == char(0))
241-
return true; // everything ends with the empty string
242-
243-
const size_t strlen = ::strlen(str);
244-
const size_t suffixlen = ::strlen(suffix);
245-
if (strlen < suffixlen)
246-
return false; // suffix must be as long or shorter than str
247-
248-
return ::strncmp(str + strlen - suffixlen, suffix, suffixlen) == 0;
303+
return strnicmp_t(str, prefix, prefixlen) == 0;
249304
}
250305

251-
inline bool endsWith(const wchar_t *str, const wchar_t *suffix)
306+
template<typename CharT> inline bool endsWith(const CharT *str, const CharT *suffix)
252307
{
253-
if (*suffix == wchar_t(0))
308+
if (*suffix == CharT(0))
254309
return true; // everything ends with the empty string
255310

256-
const size_t strlen = ::wcslen(str);
257-
const size_t suffixlen = ::wcslen(suffix);
311+
const size_t strlen = ::strlen_t(str);
312+
const size_t suffixlen = ::strlen_t(suffix);
258313
if (strlen < suffixlen)
259314
return false; // suffix must be as long or shorter than str
260315

261-
return ::wcsncmp(str + strlen - suffixlen, suffix, suffixlen) == 0;
316+
return strncmp_t(str + strlen - suffixlen, suffix, suffixlen) == 0;
262317
}
263318

264-
inline bool endsWithNoCase(const char *str, const char *suffix)
319+
template<typename CharT> inline bool endsWithNoCase(const CharT *str, const CharT *suffix)
265320
{
266-
if (*suffix == char(0))
321+
if (*suffix == CharT(0))
267322
return true; // everything ends with the empty string
268323

269-
const size_t strlen = ::strlen(str);
270-
const size_t suffixlen = ::strlen(suffix);
324+
const size_t strlen = ::strlen_t(str);
325+
const size_t suffixlen = ::strlen_t(suffix);
271326
if (strlen < suffixlen)
272327
return false; // suffix must be as long or shorter than str
273328

274-
return ::strnicmp(str + strlen - suffixlen, suffix, suffixlen) == 0;
329+
return strnicmp_t(str + strlen - suffixlen, suffix, suffixlen) == 0;
275330
}
276331

277-
inline bool endsWithNoCase(const wchar_t *str, const wchar_t *suffix)
278-
{
279-
if (*suffix == wchar_t(0))
280-
return true; // everything ends with the empty string
281-
282-
const size_t strlen = ::wcslen(str);
283-
const size_t suffixlen = ::wcslen(suffix);
284-
if (strlen < suffixlen)
285-
return false; // suffix must be as long or shorter than str
286-
287-
return ::wcsnicmp(str + strlen - suffixlen, suffix, suffixlen) == 0;
288-
}

0 commit comments

Comments
 (0)