mirror of https://github.com/OpenTTD/OpenTTD
Codechange: replace strncasecmp with case ignoring variant of StrStarts/EndsWith
parent
86786a7af6
commit
4dd5f994be
|
@ -2022,7 +2022,7 @@ DEF_CONSOLE_CMD(ConFont)
|
||||||
byte arg_index = 2;
|
byte arg_index = 2;
|
||||||
/* We may encounter "aa" or "noaa" but it must be the last argument. */
|
/* We may encounter "aa" or "noaa" but it must be the last argument. */
|
||||||
if (StrEqualsIgnoreCase(argv[arg_index], "aa") || StrEqualsIgnoreCase(argv[arg_index], "noaa")) {
|
if (StrEqualsIgnoreCase(argv[arg_index], "aa") || StrEqualsIgnoreCase(argv[arg_index], "noaa")) {
|
||||||
aa = strncasecmp(argv[arg_index++], "no", 2) != 0;
|
aa = !StrStartsWithIgnoreCase(argv[arg_index++], "no");
|
||||||
if (argc > arg_index) return false;
|
if (argc > arg_index) return false;
|
||||||
} else {
|
} else {
|
||||||
/* For <name> we want a string. */
|
/* For <name> we want a string. */
|
||||||
|
@ -2044,7 +2044,7 @@ DEF_CONSOLE_CMD(ConFont)
|
||||||
if (argc > arg_index) {
|
if (argc > arg_index) {
|
||||||
/* Last argument must be "aa" or "noaa". */
|
/* Last argument must be "aa" or "noaa". */
|
||||||
if (!StrEqualsIgnoreCase(argv[arg_index], "aa") && !StrEqualsIgnoreCase(argv[arg_index], "noaa")) return false;
|
if (!StrEqualsIgnoreCase(argv[arg_index], "aa") && !StrEqualsIgnoreCase(argv[arg_index], "noaa")) return false;
|
||||||
aa = strncasecmp(argv[arg_index++], "no", 2) != 0;
|
aa = !StrStartsWithIgnoreCase(argv[arg_index++], "no");
|
||||||
if (argc > arg_index) return false;
|
if (argc > arg_index) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2220,7 +2220,7 @@ DEF_CONSOLE_CMD(ConNewGRFProfile)
|
||||||
const std::vector<GRFFile *> &files = GetAllGRFFiles();
|
const std::vector<GRFFile *> &files = GetAllGRFFiles();
|
||||||
|
|
||||||
/* "list" sub-command */
|
/* "list" sub-command */
|
||||||
if (argc == 1 || strncasecmp(argv[1], "lis", 3) == 0) {
|
if (argc == 1 || StrStartsWithIgnoreCase(argv[1], "lis")) {
|
||||||
IConsolePrint(CC_INFO, "Loaded GRF files:");
|
IConsolePrint(CC_INFO, "Loaded GRF files:");
|
||||||
int i = 1;
|
int i = 1;
|
||||||
for (GRFFile *grf : files) {
|
for (GRFFile *grf : files) {
|
||||||
|
@ -2236,7 +2236,7 @@ DEF_CONSOLE_CMD(ConNewGRFProfile)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* "select" sub-command */
|
/* "select" sub-command */
|
||||||
if (strncasecmp(argv[1], "sel", 3) == 0 && argc >= 3) {
|
if (StrStartsWithIgnoreCase(argv[1], "sel") && argc >= 3) {
|
||||||
for (size_t argnum = 2; argnum < argc; ++argnum) {
|
for (size_t argnum = 2; argnum < argc; ++argnum) {
|
||||||
int grfnum = atoi(argv[argnum]);
|
int grfnum = atoi(argv[argnum]);
|
||||||
if (grfnum < 1 || grfnum > (int)files.size()) { // safe cast, files.size() should not be larger than a few hundred in the most extreme cases
|
if (grfnum < 1 || grfnum > (int)files.size()) { // safe cast, files.size() should not be larger than a few hundred in the most extreme cases
|
||||||
|
@ -2254,7 +2254,7 @@ DEF_CONSOLE_CMD(ConNewGRFProfile)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* "unselect" sub-command */
|
/* "unselect" sub-command */
|
||||||
if (strncasecmp(argv[1], "uns", 3) == 0 && argc >= 3) {
|
if (StrStartsWithIgnoreCase(argv[1], "uns") && argc >= 3) {
|
||||||
for (size_t argnum = 2; argnum < argc; ++argnum) {
|
for (size_t argnum = 2; argnum < argc; ++argnum) {
|
||||||
if (StrEqualsIgnoreCase(argv[argnum], "all")) {
|
if (StrEqualsIgnoreCase(argv[argnum], "all")) {
|
||||||
_newgrf_profilers.clear();
|
_newgrf_profilers.clear();
|
||||||
|
@ -2273,7 +2273,7 @@ DEF_CONSOLE_CMD(ConNewGRFProfile)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* "start" sub-command */
|
/* "start" sub-command */
|
||||||
if (strncasecmp(argv[1], "sta", 3) == 0) {
|
if (StrStartsWithIgnoreCase(argv[1], "sta")) {
|
||||||
std::string grfids;
|
std::string grfids;
|
||||||
size_t started = 0;
|
size_t started = 0;
|
||||||
for (NewGRFProfiler &pr : _newgrf_profilers) {
|
for (NewGRFProfiler &pr : _newgrf_profilers) {
|
||||||
|
@ -2309,13 +2309,13 @@ DEF_CONSOLE_CMD(ConNewGRFProfile)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* "stop" sub-command */
|
/* "stop" sub-command */
|
||||||
if (strncasecmp(argv[1], "sto", 3) == 0) {
|
if (StrStartsWithIgnoreCase(argv[1], "sto")) {
|
||||||
NewGRFProfiler::FinishAll();
|
NewGRFProfiler::FinishAll();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* "abort" sub-command */
|
/* "abort" sub-command */
|
||||||
if (strncasecmp(argv[1], "abo", 3) == 0) {
|
if (StrStartsWithIgnoreCase(argv[1], "abo")) {
|
||||||
for (NewGRFProfiler &pr : _newgrf_profilers) {
|
for (NewGRFProfiler &pr : _newgrf_profilers) {
|
||||||
pr.Abort();
|
pr.Abort();
|
||||||
}
|
}
|
||||||
|
|
|
@ -769,7 +769,7 @@ static bool ChangeWorkingDirectoryToExecutable(const char *exe)
|
||||||
bool success = false;
|
bool success = false;
|
||||||
#ifdef WITH_COCOA
|
#ifdef WITH_COCOA
|
||||||
char *app_bundle = strchr(tmp, '.');
|
char *app_bundle = strchr(tmp, '.');
|
||||||
while (app_bundle != nullptr && strncasecmp(app_bundle, ".app", 4) != 0) app_bundle = strchr(&app_bundle[1], '.');
|
while (app_bundle != nullptr && !StrStartsWithIgnoreCase(app_bundle, ".app")) app_bundle = strchr(&app_bundle[1], '.');
|
||||||
|
|
||||||
if (app_bundle != nullptr) *app_bundle = '\0';
|
if (app_bundle != nullptr) *app_bundle = '\0';
|
||||||
#endif /* WITH_COCOA */
|
#endif /* WITH_COCOA */
|
||||||
|
|
|
@ -386,7 +386,7 @@ static void FiosGetFileList(SaveLoadOperation fop, fios_getlist_callback_proc *c
|
||||||
|
|
||||||
/* found file must be directory, but not '.' or '..' */
|
/* found file must be directory, but not '.' or '..' */
|
||||||
if (FiosIsValidFile(_fios_path->c_str(), dirent, &sb) && S_ISDIR(sb.st_mode) &&
|
if (FiosIsValidFile(_fios_path->c_str(), dirent, &sb) && S_ISDIR(sb.st_mode) &&
|
||||||
(!FiosIsHiddenFile(dirent) || strncasecmp(d_name, PERSONAL_DIR, strlen(d_name)) == 0) &&
|
(!FiosIsHiddenFile(dirent) || StrStartsWithIgnoreCase(PERSONAL_DIR, d_name)) &&
|
||||||
strcmp(d_name, ".") != 0 && strcmp(d_name, "..") != 0) {
|
strcmp(d_name, ".") != 0 && strcmp(d_name, "..") != 0) {
|
||||||
fios = &file_list.emplace_back();
|
fios = &file_list.emplace_back();
|
||||||
fios->type = FIOS_TYPE_DIR;
|
fios->type = FIOS_TYPE_DIR;
|
||||||
|
|
|
@ -99,8 +99,9 @@ static uint16 ParseCode(const char *start, const char *end)
|
||||||
assert(start <= end);
|
assert(start <= end);
|
||||||
while (start < end && *start == ' ') start++;
|
while (start < end && *start == ' ') start++;
|
||||||
while (end > start && *end == ' ') end--;
|
while (end > start && *end == ' ') end--;
|
||||||
|
std::string_view str{start, (size_t)(start - end)};
|
||||||
for (uint i = 0; i < lengthof(_keycode_to_name); i++) {
|
for (uint i = 0; i < lengthof(_keycode_to_name); i++) {
|
||||||
if (strlen(_keycode_to_name[i].name) == (size_t)(end - start) && strncasecmp(start, _keycode_to_name[i].name, end - start) == 0) {
|
if (StrEqualsIgnoreCase(str, _keycode_to_name[i].name)) {
|
||||||
return _keycode_to_name[i].keycode;
|
return _keycode_to_name[i].keycode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -421,7 +421,7 @@ struct NetworkChatWindow : public Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
len = strlen(cur_name);
|
len = strlen(cur_name);
|
||||||
if (tb_len < len && strncasecmp(cur_name, tb_buf, tb_len) == 0) {
|
if (tb_len < len && StrStartsWith(cur_name, tb_buf)) {
|
||||||
/* Save the data it was before completion */
|
/* Save the data it was before completion */
|
||||||
if (!second_scan) seprintf(_chat_tab_completion_buf, lastof(_chat_tab_completion_buf), "%s", tb->buf);
|
if (!second_scan) seprintf(_chat_tab_completion_buf, lastof(_chat_tab_completion_buf), "%s", tb->buf);
|
||||||
_chat_tab_completion_active = true;
|
_chat_tab_completion_active = true;
|
||||||
|
|
|
@ -134,9 +134,9 @@ FT_Error GetFontByFaceName(const char *font_name, FT_Face *face)
|
||||||
err = FT_New_Face(_library, font_path, index, face);
|
err = FT_New_Face(_library, font_path, index, face);
|
||||||
if (err != FT_Err_Ok) break;
|
if (err != FT_Err_Ok) break;
|
||||||
|
|
||||||
if (strncasecmp(font_name, (*face)->family_name, strlen((*face)->family_name)) == 0) break;
|
if (StrStartsWithIgnoreCase(font_name, (*face)->family_name)) break;
|
||||||
/* Try english name if font name failed */
|
/* Try english name if font name failed */
|
||||||
if (strncasecmp(font_name + strlen(font_name) + 1, (*face)->family_name, strlen((*face)->family_name)) == 0) break;
|
if (StrStartsWithIgnoreCase(font_name + strlen(font_name) + 1, (*face)->family_name)) break;
|
||||||
err = FT_Err_Cannot_Open_Resource;
|
err = FT_Err_Cannot_Open_Resource;
|
||||||
|
|
||||||
} while ((FT_Long)++index != (*face)->num_faces);
|
} while ((FT_Long)++index != (*face)->num_faces);
|
||||||
|
|
17
src/stdafx.h
17
src/stdafx.h
|
@ -37,10 +37,6 @@
|
||||||
# define _GNU_SOURCE
|
# define _GNU_SOURCE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__HAIKU__) || defined(__CYGWIN__)
|
|
||||||
# include <strings.h> /* strncasecmp */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* It seems that we need to include stdint.h before anything else
|
/* It seems that we need to include stdint.h before anything else
|
||||||
* We need INT64_MAX, which for most systems comes from stdint.h. However, MSVC
|
* We need INT64_MAX, which for most systems comes from stdint.h. However, MSVC
|
||||||
* does not have stdint.h.
|
* does not have stdint.h.
|
||||||
|
@ -71,11 +67,6 @@
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__OS2__)
|
|
||||||
# include <types.h>
|
|
||||||
# define strcasecmp stricmp
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Stuff for GCC */
|
/* Stuff for GCC */
|
||||||
#if defined(__GNUC__) || (defined(__clang__) && !defined(_MSC_VER))
|
#if defined(__GNUC__) || (defined(__clang__) && !defined(_MSC_VER))
|
||||||
# define NORETURN __attribute__ ((noreturn))
|
# define NORETURN __attribute__ ((noreturn))
|
||||||
|
@ -207,9 +198,6 @@
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# define strcasecmp stricmp
|
|
||||||
# define strncasecmp strnicmp
|
|
||||||
|
|
||||||
/* MSVC doesn't have these :( */
|
/* MSVC doesn't have these :( */
|
||||||
# define S_ISDIR(mode) (mode & S_IFDIR)
|
# define S_ISDIR(mode) (mode & S_IFDIR)
|
||||||
# define S_ISREG(mode) (mode & S_IFREG)
|
# define S_ISREG(mode) (mode & S_IFREG)
|
||||||
|
@ -411,11 +399,6 @@ void NORETURN AssertFailedError(int line, const char *file, const char *expressi
|
||||||
# define assert(expression) if (unlikely(!(expression))) AssertFailedError(__LINE__, __FILE__, #expression);
|
# define assert(expression) if (unlikely(!(expression))) AssertFailedError(__LINE__, __FILE__, #expression);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(OPENBSD)
|
|
||||||
/* OpenBSD uses strcasecmp(3) */
|
|
||||||
# define _stricmp strcasecmp
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MAX_PATH)
|
#if defined(MAX_PATH)
|
||||||
/* It's already defined, no need to override */
|
/* It's already defined, no need to override */
|
||||||
#elif defined(PATH_MAX) && PATH_MAX > 0
|
#elif defined(PATH_MAX) && PATH_MAX > 0
|
||||||
|
|
|
@ -23,26 +23,27 @@
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#include <errno.h> // required by vsnprintf implementation for MSVC
|
# include <errno.h> // required by vsnprintf implementation for MSVC
|
||||||
|
# define strncasecmp strnicmp
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "os/windows/win32.h"
|
# include "os/windows/win32.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_UNISCRIBE
|
#ifdef WITH_UNISCRIBE
|
||||||
#include "os/windows/string_uniscribe.h"
|
# include "os/windows/string_uniscribe.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_ICU_I18N
|
#ifdef WITH_ICU_I18N
|
||||||
/* Required by strnatcmp. */
|
/* Required by strnatcmp. */
|
||||||
#include <unicode/ustring.h>
|
# include <unicode/ustring.h>
|
||||||
#include "language.h"
|
# include "language.h"
|
||||||
#include "gfx_func.h"
|
# include "gfx_func.h"
|
||||||
#endif /* WITH_ICU_I18N */
|
#endif /* WITH_ICU_I18N */
|
||||||
|
|
||||||
#if defined(WITH_COCOA)
|
#if defined(WITH_COCOA)
|
||||||
#include "os/macosx/string_osx.h"
|
# include "os/macosx/string_osx.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The function vsnprintf is used internally to perform the required formatting
|
/* The function vsnprintf is used internally to perform the required formatting
|
||||||
|
@ -355,6 +356,18 @@ bool StrStartsWith(const std::string_view str, const std::string_view prefix)
|
||||||
return str.compare(0, prefix_len, prefix, 0, prefix_len) == 0;
|
return str.compare(0, prefix_len, prefix, 0, prefix_len) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the given string starts with the given prefix, ignoring case.
|
||||||
|
* @param str The string to look at.
|
||||||
|
* @param prefix The prefix to look for.
|
||||||
|
* @return True iff the begin of the string is the same as the prefix, ignoring case.
|
||||||
|
*/
|
||||||
|
bool StrStartsWithIgnoreCase(std::string_view str, const std::string_view prefix)
|
||||||
|
{
|
||||||
|
if (str.size() < prefix.size()) return false;
|
||||||
|
return StrEqualsIgnoreCase(str.substr(0, prefix.size()), prefix);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether the given string ends with the given suffix.
|
* Check whether the given string ends with the given suffix.
|
||||||
* @param str The string to look at.
|
* @param str The string to look at.
|
||||||
|
@ -396,6 +409,18 @@ struct CaseInsensitiveCharTraits : public std::char_traits<char> {
|
||||||
/** Case insensitive string view. */
|
/** Case insensitive string view. */
|
||||||
typedef std::basic_string_view<char, CaseInsensitiveCharTraits> CaseInsensitiveStringView;
|
typedef std::basic_string_view<char, CaseInsensitiveCharTraits> CaseInsensitiveStringView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the given string ends with the given suffix, ignoring case.
|
||||||
|
* @param str The string to look at.
|
||||||
|
* @param suffix The suffix to look for.
|
||||||
|
* @return True iff the end of the string is the same as the suffix, ignoring case.
|
||||||
|
*/
|
||||||
|
bool StrEndsWithIgnoreCase(std::string_view str, const std::string_view suffix)
|
||||||
|
{
|
||||||
|
if (str.size() < suffix.size()) return false;
|
||||||
|
return StrEqualsIgnoreCase(str.substr(str.size() - suffix.size()), suffix);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares two string( view)s, while ignoring the case of the characters.
|
* Compares two string( view)s, while ignoring the case of the characters.
|
||||||
* @param str1 The first string.
|
* @param str1 The first string.
|
||||||
|
|
|
@ -48,11 +48,13 @@ void str_strip_colours(char *str);
|
||||||
bool strtolower(char *str);
|
bool strtolower(char *str);
|
||||||
bool strtolower(std::string &str, std::string::size_type offs = 0);
|
bool strtolower(std::string &str, std::string::size_type offs = 0);
|
||||||
|
|
||||||
bool StrValid(const char *str, const char *last) NOACCESS(2);
|
[[nodiscard]] bool StrValid(const char *str, const char *last) NOACCESS(2);
|
||||||
void StrTrimInPlace(std::string &str);
|
void StrTrimInPlace(std::string &str);
|
||||||
|
|
||||||
bool StrStartsWith(const std::string_view str, const std::string_view prefix);
|
[[nodiscard]] bool StrStartsWith(const std::string_view str, const std::string_view prefix);
|
||||||
bool StrEndsWith(const std::string_view str, const std::string_view suffix);
|
[[nodiscard]] bool StrStartsWithIgnoreCase(std::string_view str, const std::string_view prefix);
|
||||||
|
[[nodiscard]] bool StrEndsWith(const std::string_view str, const std::string_view suffix);
|
||||||
|
[[nodiscard]] bool StrEndsWithIgnoreCase(std::string_view str, const std::string_view suffix);
|
||||||
|
|
||||||
[[nodiscard]] int StrCompareIgnoreCase(const std::string_view str1, const std::string_view str2);
|
[[nodiscard]] int StrCompareIgnoreCase(const std::string_view str1, const std::string_view str2);
|
||||||
[[nodiscard]] bool StrEqualsIgnoreCase(const std::string_view str1, const std::string_view str2);
|
[[nodiscard]] bool StrEqualsIgnoreCase(const std::string_view str1, const std::string_view str2);
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
|
|
||||||
#include "../string_func.h"
|
#include "../string_func.h"
|
||||||
|
|
||||||
|
/**** String compare/equals *****/
|
||||||
|
|
||||||
TEST_CASE("StrCompareIgnoreCase - std::string")
|
TEST_CASE("StrCompareIgnoreCase - std::string")
|
||||||
{
|
{
|
||||||
/* Same string, with different cases. */
|
/* Same string, with different cases. */
|
||||||
|
@ -158,3 +160,359 @@ TEST_CASE("StrEqualsIgnoreCase - std::string_view")
|
||||||
CHECK(!StrEqualsIgnoreCase(base.substr(0, 1), base.substr(0, 2))); // Same position, different lengths
|
CHECK(!StrEqualsIgnoreCase(base.substr(0, 1), base.substr(0, 2))); // Same position, different lengths
|
||||||
CHECK(!StrEqualsIgnoreCase(base.substr(0, 2), base.substr(0, 1))); // Same position, different lengths
|
CHECK(!StrEqualsIgnoreCase(base.substr(0, 2), base.substr(0, 1))); // Same position, different lengths
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**** String starts with *****/
|
||||||
|
|
||||||
|
TEST_CASE("StrStartsWith - std::string")
|
||||||
|
{
|
||||||
|
/* Everything starts with an empty prefix. */
|
||||||
|
CHECK(StrStartsWith(std::string{""}, std::string{""}));
|
||||||
|
CHECK(StrStartsWith(std::string{"a"}, std::string{""}));
|
||||||
|
|
||||||
|
/* Equal strings. */
|
||||||
|
CHECK(StrStartsWith(std::string{"a"}, std::string{"a"}));
|
||||||
|
CHECK(StrStartsWith(std::string{"A"}, std::string{"A"}));
|
||||||
|
|
||||||
|
/* Starts with same. */
|
||||||
|
CHECK(StrStartsWith(std::string{"ab"}, std::string{"a"}));
|
||||||
|
CHECK(StrStartsWith(std::string{"Ab"}, std::string{"A"}));
|
||||||
|
|
||||||
|
/* Different cases. */
|
||||||
|
CHECK(!StrStartsWith(std::string{"a"}, std::string{"A"}));
|
||||||
|
CHECK(!StrStartsWith(std::string{"A"}, std::string{"a"}));
|
||||||
|
CHECK(!StrStartsWith(std::string{"ab"}, std::string{"A"}));
|
||||||
|
CHECK(!StrStartsWith(std::string{"Ab"}, std::string{"a"}));
|
||||||
|
|
||||||
|
/* Does not start the same. */
|
||||||
|
CHECK(!StrStartsWith(std::string{""}, std::string{"b"}));
|
||||||
|
CHECK(!StrStartsWith(std::string{"a"}, std::string{"b"}));
|
||||||
|
CHECK(!StrStartsWith(std::string{"b"}, std::string{"a"}));
|
||||||
|
CHECK(!StrStartsWith(std::string{"a"}, std::string{"aa"}));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("StrStartsWith - char pointer")
|
||||||
|
{
|
||||||
|
CHECK(StrStartsWith("", ""));
|
||||||
|
CHECK(StrStartsWith("a", ""));
|
||||||
|
|
||||||
|
/* Equal strings. */
|
||||||
|
CHECK(StrStartsWith("a", "a"));
|
||||||
|
CHECK(StrStartsWith("A", "A"));
|
||||||
|
|
||||||
|
/* Starts with same. */
|
||||||
|
CHECK(StrStartsWith("ab", "a"));
|
||||||
|
CHECK(StrStartsWith("Ab", "A"));
|
||||||
|
|
||||||
|
/* Different cases. */
|
||||||
|
CHECK(!StrStartsWith("a", "A"));
|
||||||
|
CHECK(!StrStartsWith("A", "a"));
|
||||||
|
CHECK(!StrStartsWith("ab", "A"));
|
||||||
|
CHECK(!StrStartsWith("Ab", "a"));
|
||||||
|
|
||||||
|
/* Does not start the same. */
|
||||||
|
CHECK(!StrStartsWith("", "b"));
|
||||||
|
CHECK(!StrStartsWith("a", "b"));
|
||||||
|
CHECK(!StrStartsWith("b", "a"));
|
||||||
|
CHECK(!StrStartsWith("a", "aa"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("StrStartsWith - std::string_view")
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* With std::string_view the only way to access the data is via .data(),
|
||||||
|
* which does not guarantee the termination that would be required by
|
||||||
|
* things such as stricmp/strcasecmp. So, just passing .data() into stricmp
|
||||||
|
* or strcasecmp would fail if it does not account for the length of the
|
||||||
|
* view. Thus, contrary to the string/char* tests, this uses the same base
|
||||||
|
* string but gets different sections to trigger these corner cases.
|
||||||
|
*/
|
||||||
|
std::string_view base{"aabAb"};
|
||||||
|
|
||||||
|
/* Everything starts with an empty prefix. */
|
||||||
|
CHECK(StrStartsWith(base.substr(0, 0), base.substr(1, 0))); // Different positions
|
||||||
|
CHECK(StrStartsWith(base.substr(0, 1), base.substr(0, 0)));
|
||||||
|
|
||||||
|
/* Equals string. */
|
||||||
|
CHECK(StrStartsWith(base.substr(0, 1), base.substr(1, 1))); // Different positions
|
||||||
|
CHECK(StrStartsWith(base.substr(3, 1), base.substr(3, 1)));
|
||||||
|
|
||||||
|
/* Starts with same. */
|
||||||
|
CHECK(StrStartsWith(base.substr(1, 2), base.substr(0, 1)));
|
||||||
|
CHECK(StrStartsWith(base.substr(3, 2), base.substr(3, 1)));
|
||||||
|
|
||||||
|
/* Different cases. */
|
||||||
|
CHECK(!StrStartsWith(base.substr(0, 1), base.substr(3, 1)));
|
||||||
|
CHECK(!StrStartsWith(base.substr(3, 1), base.substr(0, 1)));
|
||||||
|
CHECK(!StrStartsWith(base.substr(1, 2), base.substr(3, 1)));
|
||||||
|
CHECK(!StrStartsWith(base.substr(3, 2), base.substr(0, 1)));
|
||||||
|
|
||||||
|
/* Does not start the same. */
|
||||||
|
CHECK(!StrStartsWith(base.substr(2, 0), base.substr(2, 1)));
|
||||||
|
CHECK(!StrStartsWith(base.substr(0, 1), base.substr(2, 1)));
|
||||||
|
CHECK(!StrStartsWith(base.substr(2, 1), base.substr(0, 1)));
|
||||||
|
CHECK(!StrStartsWith(base.substr(0, 1), base.substr(0, 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("StrStartsWithIgnoreCase - std::string")
|
||||||
|
{
|
||||||
|
/* Everything starts with an empty prefix. */
|
||||||
|
CHECK(StrStartsWithIgnoreCase(std::string{""}, std::string{""}));
|
||||||
|
CHECK(StrStartsWithIgnoreCase(std::string{"a"}, std::string{""}));
|
||||||
|
|
||||||
|
/* Equals string, ignoring case. */
|
||||||
|
CHECK(StrStartsWithIgnoreCase(std::string{"a"}, std::string{"a"}));
|
||||||
|
CHECK(StrStartsWithIgnoreCase(std::string{"a"}, std::string{"A"}));
|
||||||
|
CHECK(StrStartsWithIgnoreCase(std::string{"A"}, std::string{"a"}));
|
||||||
|
CHECK(StrStartsWithIgnoreCase(std::string{"A"}, std::string{"A"}));
|
||||||
|
|
||||||
|
/* Starts with same, ignoring case. */
|
||||||
|
CHECK(StrStartsWithIgnoreCase(std::string{"ab"}, std::string{"a"}));
|
||||||
|
CHECK(StrStartsWithIgnoreCase(std::string{"ab"}, std::string{"A"}));
|
||||||
|
CHECK(StrStartsWithIgnoreCase(std::string{"Ab"}, std::string{"a"}));
|
||||||
|
CHECK(StrStartsWithIgnoreCase(std::string{"Ab"}, std::string{"A"}));
|
||||||
|
|
||||||
|
/* Does not start the same. */
|
||||||
|
CHECK(!StrStartsWithIgnoreCase(std::string{""}, std::string{"b"}));
|
||||||
|
CHECK(!StrStartsWithIgnoreCase(std::string{"a"}, std::string{"b"}));
|
||||||
|
CHECK(!StrStartsWithIgnoreCase(std::string{"b"}, std::string{"a"}));
|
||||||
|
CHECK(!StrStartsWithIgnoreCase(std::string{"a"}, std::string{"aa"}));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("StrStartsWithIgnoreCase - char pointer")
|
||||||
|
{
|
||||||
|
/* Everything starts with an empty prefix. */
|
||||||
|
CHECK(StrStartsWithIgnoreCase("", ""));
|
||||||
|
CHECK(StrStartsWithIgnoreCase("a", ""));
|
||||||
|
|
||||||
|
/* Equals string, ignoring case. */
|
||||||
|
CHECK(StrStartsWithIgnoreCase("a", "a"));
|
||||||
|
CHECK(StrStartsWithIgnoreCase("a", "A"));
|
||||||
|
CHECK(StrStartsWithIgnoreCase("A", "a"));
|
||||||
|
CHECK(StrStartsWithIgnoreCase("A", "A"));
|
||||||
|
|
||||||
|
/* Starts with same, ignoring case. */
|
||||||
|
CHECK(StrStartsWithIgnoreCase("ab", "a"));
|
||||||
|
CHECK(StrStartsWithIgnoreCase("ab", "A"));
|
||||||
|
CHECK(StrStartsWithIgnoreCase("Ab", "a"));
|
||||||
|
CHECK(StrStartsWithIgnoreCase("Ab", "A"));
|
||||||
|
|
||||||
|
/* Does not start the same. */
|
||||||
|
CHECK(!StrStartsWithIgnoreCase("", "b"));
|
||||||
|
CHECK(!StrStartsWithIgnoreCase("a", "b"));
|
||||||
|
CHECK(!StrStartsWithIgnoreCase("b", "a"));
|
||||||
|
CHECK(!StrStartsWithIgnoreCase("a", "aa"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("StrStartsWithIgnoreCase - std::string_view")
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* With std::string_view the only way to access the data is via .data(),
|
||||||
|
* which does not guarantee the termination that would be required by
|
||||||
|
* things such as stricmp/strcasecmp. So, just passing .data() into stricmp
|
||||||
|
* or strcasecmp would fail if it does not account for the length of the
|
||||||
|
* view. Thus, contrary to the string/char* tests, this uses the same base
|
||||||
|
* string but gets different sections to trigger these corner cases.
|
||||||
|
*/
|
||||||
|
std::string_view base{"aabAb"};
|
||||||
|
|
||||||
|
/* Everything starts with an empty prefix. */
|
||||||
|
CHECK(StrStartsWithIgnoreCase(base.substr(0, 0), base.substr(1, 0))); // Different positions
|
||||||
|
CHECK(StrStartsWithIgnoreCase(base.substr(0, 1), base.substr(0, 0)));
|
||||||
|
|
||||||
|
/* Equals string, ignoring case. */
|
||||||
|
CHECK(StrStartsWithIgnoreCase(base.substr(0, 1), base.substr(1, 1))); // Different positions
|
||||||
|
CHECK(StrStartsWithIgnoreCase(base.substr(0, 1), base.substr(3, 1)));
|
||||||
|
CHECK(StrStartsWithIgnoreCase(base.substr(3, 1), base.substr(0, 1)));
|
||||||
|
CHECK(StrStartsWithIgnoreCase(base.substr(3, 1), base.substr(3, 1)));
|
||||||
|
|
||||||
|
/* Starts with same, ignoring case. */
|
||||||
|
CHECK(StrStartsWithIgnoreCase(base.substr(1, 2), base.substr(0, 1)));
|
||||||
|
CHECK(StrStartsWithIgnoreCase(base.substr(1, 2), base.substr(3, 1)));
|
||||||
|
CHECK(StrStartsWithIgnoreCase(base.substr(3, 2), base.substr(0, 1)));
|
||||||
|
CHECK(StrStartsWithIgnoreCase(base.substr(3, 2), base.substr(3, 1)));
|
||||||
|
|
||||||
|
/* Does not start the same. */
|
||||||
|
CHECK(!StrStartsWithIgnoreCase(base.substr(2, 0), base.substr(2, 1)));
|
||||||
|
CHECK(!StrStartsWithIgnoreCase(base.substr(0, 1), base.substr(2, 1)));
|
||||||
|
CHECK(!StrStartsWithIgnoreCase(base.substr(2, 1), base.substr(0, 1)));
|
||||||
|
CHECK(!StrStartsWithIgnoreCase(base.substr(0, 1), base.substr(0, 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** String ends with *****/
|
||||||
|
|
||||||
|
TEST_CASE("StrEndsWith - std::string")
|
||||||
|
{
|
||||||
|
/* Everything ends with an empty prefix. */
|
||||||
|
CHECK(StrEndsWith(std::string{""}, std::string{""}));
|
||||||
|
CHECK(StrEndsWith(std::string{"a"}, std::string{""}));
|
||||||
|
|
||||||
|
/* Equal strings. */
|
||||||
|
CHECK(StrEndsWith(std::string{"a"}, std::string{"a"}));
|
||||||
|
CHECK(StrEndsWith(std::string{"A"}, std::string{"A"}));
|
||||||
|
|
||||||
|
/* Ends with same. */
|
||||||
|
CHECK(StrEndsWith(std::string{"ba"}, std::string{"a"}));
|
||||||
|
CHECK(StrEndsWith(std::string{"bA"}, std::string{"A"}));
|
||||||
|
|
||||||
|
/* Different cases. */
|
||||||
|
CHECK(!StrEndsWith(std::string{"a"}, std::string{"A"}));
|
||||||
|
CHECK(!StrEndsWith(std::string{"A"}, std::string{"a"}));
|
||||||
|
CHECK(!StrEndsWith(std::string{"ba"}, std::string{"A"}));
|
||||||
|
CHECK(!StrEndsWith(std::string{"bA"}, std::string{"a"}));
|
||||||
|
|
||||||
|
/* Does not end the same. */
|
||||||
|
CHECK(!StrEndsWith(std::string{""}, std::string{"b"}));
|
||||||
|
CHECK(!StrEndsWith(std::string{"a"}, std::string{"b"}));
|
||||||
|
CHECK(!StrEndsWith(std::string{"b"}, std::string{"a"}));
|
||||||
|
CHECK(!StrEndsWith(std::string{"a"}, std::string{"aa"}));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("StrEndsWith - char pointer")
|
||||||
|
{
|
||||||
|
CHECK(StrEndsWith("", ""));
|
||||||
|
CHECK(StrEndsWith("a", ""));
|
||||||
|
|
||||||
|
/* Equal strings. */
|
||||||
|
CHECK(StrEndsWith("a", "a"));
|
||||||
|
CHECK(StrEndsWith("A", "A"));
|
||||||
|
|
||||||
|
/* Ends with same. */
|
||||||
|
CHECK(StrEndsWith("ba", "a"));
|
||||||
|
CHECK(StrEndsWith("bA", "A"));
|
||||||
|
|
||||||
|
/* Different cases. */
|
||||||
|
CHECK(!StrEndsWith("a", "A"));
|
||||||
|
CHECK(!StrEndsWith("A", "a"));
|
||||||
|
CHECK(!StrEndsWith("ba", "A"));
|
||||||
|
CHECK(!StrEndsWith("bA", "a"));
|
||||||
|
|
||||||
|
/* Does not end the same. */
|
||||||
|
CHECK(!StrEndsWith("", "b"));
|
||||||
|
CHECK(!StrEndsWith("a", "b"));
|
||||||
|
CHECK(!StrEndsWith("b", "a"));
|
||||||
|
CHECK(!StrEndsWith("a", "aa"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("StrEndsWith - std::string_view")
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* With std::string_view the only way to access the data is via .data(),
|
||||||
|
* which does not guarantee the termination that would be required by
|
||||||
|
* things such as stricmp/strcasecmp. So, just passing .data() into stricmp
|
||||||
|
* or strcasecmp would fail if it does not account for the length of the
|
||||||
|
* view. Thus, contrary to the string/char* tests, this uses the same base
|
||||||
|
* string but gets different sections to trigger these corner cases.
|
||||||
|
*/
|
||||||
|
std::string_view base{"aabAba"};
|
||||||
|
|
||||||
|
/* Everything ends with an empty prefix. */
|
||||||
|
CHECK(StrEndsWith(base.substr(0, 0), base.substr(1, 0))); // Different positions
|
||||||
|
CHECK(StrEndsWith(base.substr(0, 1), base.substr(0, 0)));
|
||||||
|
|
||||||
|
/* Equals string. */
|
||||||
|
CHECK(StrEndsWith(base.substr(0, 1), base.substr(1, 1))); // Different positions
|
||||||
|
CHECK(StrEndsWith(base.substr(3, 1), base.substr(3, 1)));
|
||||||
|
|
||||||
|
/* Ends with same. */
|
||||||
|
CHECK(StrEndsWith(base.substr(4, 2), base.substr(0, 1)));
|
||||||
|
CHECK(StrEndsWith(base.substr(2, 2), base.substr(3, 1)));
|
||||||
|
|
||||||
|
/* Different cases. */
|
||||||
|
CHECK(!StrEndsWith(base.substr(0, 1), base.substr(3, 1)));
|
||||||
|
CHECK(!StrEndsWith(base.substr(3, 1), base.substr(0, 1)));
|
||||||
|
CHECK(!StrEndsWith(base.substr(4, 2), base.substr(3, 1)));
|
||||||
|
CHECK(!StrEndsWith(base.substr(2, 2), base.substr(0, 1)));
|
||||||
|
|
||||||
|
/* Does not end the same. */
|
||||||
|
CHECK(!StrEndsWith(base.substr(2, 0), base.substr(2, 1)));
|
||||||
|
CHECK(!StrEndsWith(base.substr(0, 1), base.substr(2, 1)));
|
||||||
|
CHECK(!StrEndsWith(base.substr(2, 1), base.substr(0, 1)));
|
||||||
|
CHECK(!StrEndsWith(base.substr(0, 1), base.substr(0, 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("StrEndsWithIgnoreCase - std::string")
|
||||||
|
{
|
||||||
|
/* Everything ends with an empty prefix. */
|
||||||
|
CHECK(StrEndsWithIgnoreCase(std::string{""}, std::string{""}));
|
||||||
|
CHECK(StrEndsWithIgnoreCase(std::string{"a"}, std::string{""}));
|
||||||
|
|
||||||
|
/* Equals string, ignoring case. */
|
||||||
|
CHECK(StrEndsWithIgnoreCase(std::string{"a"}, std::string{"a"}));
|
||||||
|
CHECK(StrEndsWithIgnoreCase(std::string{"a"}, std::string{"A"}));
|
||||||
|
CHECK(StrEndsWithIgnoreCase(std::string{"A"}, std::string{"a"}));
|
||||||
|
CHECK(StrEndsWithIgnoreCase(std::string{"A"}, std::string{"A"}));
|
||||||
|
|
||||||
|
/* Ends with same, ignoring case. */
|
||||||
|
CHECK(StrEndsWithIgnoreCase(std::string{"ba"}, std::string{"a"}));
|
||||||
|
CHECK(StrEndsWithIgnoreCase(std::string{"ba"}, std::string{"A"}));
|
||||||
|
CHECK(StrEndsWithIgnoreCase(std::string{"bA"}, std::string{"a"}));
|
||||||
|
CHECK(StrEndsWithIgnoreCase(std::string{"bA"}, std::string{"A"}));
|
||||||
|
|
||||||
|
/* Does not end the same. */
|
||||||
|
CHECK(!StrEndsWithIgnoreCase(std::string{""}, std::string{"b"}));
|
||||||
|
CHECK(!StrEndsWithIgnoreCase(std::string{"a"}, std::string{"b"}));
|
||||||
|
CHECK(!StrEndsWithIgnoreCase(std::string{"b"}, std::string{"a"}));
|
||||||
|
CHECK(!StrEndsWithIgnoreCase(std::string{"a"}, std::string{"aa"}));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("StrEndsWithIgnoreCase - char pointer")
|
||||||
|
{
|
||||||
|
/* Everything ends with an empty prefix. */
|
||||||
|
CHECK(StrEndsWithIgnoreCase("", ""));
|
||||||
|
CHECK(StrEndsWithIgnoreCase("a", ""));
|
||||||
|
|
||||||
|
/* Equals string, ignoring case. */
|
||||||
|
CHECK(StrEndsWithIgnoreCase("a", "a"));
|
||||||
|
CHECK(StrEndsWithIgnoreCase("a", "A"));
|
||||||
|
CHECK(StrEndsWithIgnoreCase("A", "a"));
|
||||||
|
CHECK(StrEndsWithIgnoreCase("A", "A"));
|
||||||
|
|
||||||
|
/* Ends with same, ignoring case. */
|
||||||
|
CHECK(StrEndsWithIgnoreCase("ba", "a"));
|
||||||
|
CHECK(StrEndsWithIgnoreCase("ba", "A"));
|
||||||
|
CHECK(StrEndsWithIgnoreCase("bA", "a"));
|
||||||
|
CHECK(StrEndsWithIgnoreCase("bA", "A"));
|
||||||
|
|
||||||
|
/* Does not end the same. */
|
||||||
|
CHECK(!StrEndsWithIgnoreCase("", "b"));
|
||||||
|
CHECK(!StrEndsWithIgnoreCase("a", "b"));
|
||||||
|
CHECK(!StrEndsWithIgnoreCase("b", "a"));
|
||||||
|
CHECK(!StrEndsWithIgnoreCase("a", "aa"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("StrEndsWithIgnoreCase - std::string_view")
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* With std::string_view the only way to access the data is via .data(),
|
||||||
|
* which does not guarantee the termination that would be required by
|
||||||
|
* things such as stricmp/strcasecmp. So, just passing .data() into stricmp
|
||||||
|
* or strcasecmp would fail if it does not account for the length of the
|
||||||
|
* view. Thus, contrary to the string/char* tests, this uses the same base
|
||||||
|
* string but gets different sections to trigger these corner cases.
|
||||||
|
*/
|
||||||
|
std::string_view base{"aabAba"};
|
||||||
|
|
||||||
|
/* Everything ends with an empty prefix. */
|
||||||
|
CHECK(StrEndsWithIgnoreCase(base.substr(0, 0), base.substr(1, 0))); // Different positions
|
||||||
|
CHECK(StrEndsWithIgnoreCase(base.substr(0, 1), base.substr(0, 0)));
|
||||||
|
|
||||||
|
/* Equals string, ignoring case. */
|
||||||
|
CHECK(StrEndsWithIgnoreCase(base.substr(0, 1), base.substr(1, 1))); // Different positions
|
||||||
|
CHECK(StrEndsWithIgnoreCase(base.substr(0, 1), base.substr(3, 1)));
|
||||||
|
CHECK(StrEndsWithIgnoreCase(base.substr(3, 1), base.substr(0, 1)));
|
||||||
|
CHECK(StrEndsWithIgnoreCase(base.substr(3, 1), base.substr(3, 1)));
|
||||||
|
|
||||||
|
/* Ends with same, ignoring case. */
|
||||||
|
CHECK(StrEndsWithIgnoreCase(base.substr(2, 2), base.substr(0, 1)));
|
||||||
|
CHECK(StrEndsWithIgnoreCase(base.substr(2, 2), base.substr(3, 1)));
|
||||||
|
CHECK(StrEndsWithIgnoreCase(base.substr(4, 2), base.substr(0, 1)));
|
||||||
|
CHECK(StrEndsWithIgnoreCase(base.substr(4, 2), base.substr(3, 1)));
|
||||||
|
|
||||||
|
/* Does not end the same. */
|
||||||
|
CHECK(!StrEndsWithIgnoreCase(base.substr(2, 0), base.substr(2, 1)));
|
||||||
|
CHECK(!StrEndsWithIgnoreCase(base.substr(0, 1), base.substr(2, 1)));
|
||||||
|
CHECK(!StrEndsWithIgnoreCase(base.substr(2, 1), base.substr(0, 1)));
|
||||||
|
CHECK(!StrEndsWithIgnoreCase(base.substr(0, 1), base.substr(0, 2)));
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue