summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/corestr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/corestr.cpp')
-rw-r--r--src/lib/util/corestr.cpp219
1 files changed, 100 insertions, 119 deletions
diff --git a/src/lib/util/corestr.cpp b/src/lib/util/corestr.cpp
index 5add3ed302f..9fa0a3990a2 100644
--- a/src/lib/util/corestr.cpp
+++ b/src/lib/util/corestr.cpp
@@ -9,27 +9,36 @@
****************************************************************************/
#include "corestr.h"
-#include "osdcore.h"
#include <algorithm>
+#include <iterator>
#include <memory>
-#include <ctype.h>
-#include <stdlib.h>
+#include <cctype>
+#include <cstdint>
+#include <cstdlib>
/*-------------------------------------------------
core_stricmp - case-insensitive string compare
-------------------------------------------------*/
-int core_stricmp(const char *s1, const char *s2)
+int core_stricmp(std::string_view s1, std::string_view s2)
{
- for (;;)
+ auto s1_iter = s1.begin();
+ auto s2_iter = s2.begin();
+ while (true)
{
- int c1 = tolower((uint8_t)*s1++);
- int c2 = tolower((uint8_t)*s2++);
- if (c1 == 0 || c1 != c2)
- return c1 - c2;
+ if (s1.end() == s1_iter)
+ return (s2.end() == s2_iter) ? 0 : -1;
+ else if (s2.end() == s2_iter)
+ return 1;
+
+ const int c1 = tolower(uint8_t(*s1_iter++));
+ const int c2 = tolower(uint8_t(*s2_iter++));
+ const int diff = c1 - c2;
+ if (diff)
+ return diff;
}
}
@@ -55,70 +64,42 @@ int core_strnicmp(const char *s1, const char *s2, size_t n)
/*-------------------------------------------------
core_strwildcmp - case-insensitive wildcard
- string compare (up to 16 characters at the
- moment)
+ string compare
-------------------------------------------------*/
-int core_strwildcmp(const char *sp1, const char *sp2)
+int core_strwildcmp(std::string_view s1, std::string_view s2)
{
- char s1[17], s2[17];
- size_t i, l1, l2;
- char *p;
-
- //assert(strlen(sp1) < 16);
- //assert(strlen(sp2) < 16);
-
- if (sp1[0] == 0) strcpy(s1, "*");
- else { strncpy(s1, sp1, 16); s1[16] = 0; }
-
- if (sp2[0] == 0) strcpy(s2, "*");
- else { strncpy(s2, sp2, 16); s2[16] = 0; }
-
- p = strchr(s1, '*');
- if (p)
- {
- for (i = p - s1; i < 16; i++) s1[i] = '?';
- s1[16] = 0;
- }
-
- p = strchr(s2, '*');
- if (p)
- {
- for (i = p - s2; i < 16; i++) s2[i] = '?';
- s2[16] = 0;
- }
-
- l1 = strlen(s1);
- if (l1 < 16)
+ // slight tweak of core_stricmp() logic
+ auto s1_iter = s1.begin();
+ auto s2_iter = s2.begin();
+ while (true)
{
- for (i = l1 + 1; i < 16; i++) s1[i] = ' ';
- s1[16] = 0;
+ if ((s1.end() != s1_iter && *s1_iter == '*')
+ || (s2.end() != s2_iter && *s2_iter == '*'))
+ return 0;
+
+ if (s1.end() == s1_iter)
+ return (s2.end() == s2_iter) ? 0 : -1;
+ else if (s2.end() == s2_iter)
+ return 1;
+
+ const int c1 = tolower(uint8_t(*s1_iter++));
+ const int c2 = tolower(uint8_t(*s2_iter++));
+ const int diff = (c1 != '?' && c2 != '?')
+ ? c1 - c2
+ : 0;
+ if (diff)
+ return diff;
}
-
- l2 = strlen(s2);
- if (l2 < 16)
- {
- for (i = l2 + 1; i < 16; i++) s2[i] = ' ';
- s2[16] = 0;
- }
-
- for (i = 0; i < 16; i++)
- {
- if (s1[i] == '?' && s2[i] != '?') s1[i] = s2[i];
- if (s2[i] == '?' && s1[i] != '?') s2[i] = s1[i];
- }
-
- return core_stricmp(s1, s2);
}
-bool core_iswildstr(const char *sp)
+bool core_iswildstr(std::string_view s)
{
- for ( ; sp && *sp; sp++)
+ auto iter = std::find_if(s.begin(), s.end(), [](char c)
{
- if (('?' == *sp) || ('*' == *sp))
- return true;
- }
- return false;
+ return c == '?' || c == '*';
+ });
+ return iter != s.end();
}
@@ -126,18 +107,6 @@ bool core_iswildstr(const char *sp)
std::string helpers
-------------------------------------------------*/
-#include <algorithm>
-
-int strcatvprintf(std::string &str, const char *format, va_list args)
-{
- char tempbuf[4096];
- int result = vsprintf(tempbuf, format, args);
-
- // set the result
- str.append(tempbuf);
- return result;
-}
-
void strdelchr(std::string& str, char chr)
{
for (size_t i = 0; i < str.length(); i++)
@@ -158,61 +127,39 @@ void strreplacechr(std::string& str, char ch, char newch)
}
}
-static std::string &internal_strtrimspace(std::string& str, bool right_only)
-{
- // identify the start
- std::string::iterator start = str.begin();
- if (!right_only)
- {
- start = std::find_if(
- str.begin(),
- str.end(),
- [](char c) { return !isspace(uint8_t(c)); });
- }
-
- // identify the end
- std::string::iterator end = std::find_if(
- str.rbegin(),
- std::string::reverse_iterator(start),
- [](char c) { return !isspace(uint8_t(c)); }).base();
-
- // extract the string
- str = end > start
- ? str.substr(start - str.begin(), end - start)
- : "";
- return str;
-}
-
-std::string &strtrimspace(std::string& str)
+std::string_view strtrimspace(std::string_view str)
{
- return internal_strtrimspace(str, false);
+ std::string_view str2 = strtrimleft(str, [] (char c) { return !isspace(uint8_t(c)); });
+ return strtrimright(str2, [] (char c) { return !isspace(uint8_t(c)); });
}
-std::string &strtrimrightspace(std::string& str)
+std::string_view strtrimrightspace(std::string_view str)
{
- return internal_strtrimspace(str, true);
+ return strtrimright(str, [] (char c) { return !isspace(uint8_t(c)); });
}
-std::string &strmakeupper(std::string& str)
+std::string strmakeupper(std::string_view str)
{
- std::transform(str.begin(), str.end(), str.begin(), ::toupper);
- return str;
+ std::string result;
+ std::transform(str.begin(), str.end(), std::back_inserter(result), ::toupper);
+ return result;
}
/**
- * @fn std::string &strmakelower(std::string& str)
+ * @fn std::string strmakelower(std::string_view str)
*
- * @brief Changes the given string to lower case.
+ * @brief Returns a lower case version of the given string.
*
- * @param [in,out] str The string to make lower case
+ * @param [in] str The string to make lower case
*
- * @return A reference to the original std::string having been changed to lower case
+ * @return A new std::string having been changed to lower case
*/
-std::string &strmakelower(std::string& str)
+std::string strmakelower(std::string_view str)
{
- std::transform(str.begin(), str.end(), str.begin(), ::tolower);
- return str;
+ std::string result;
+ std::transform(str.begin(), str.end(), std::back_inserter(result), ::tolower);
+ return result;
}
/**
@@ -244,7 +191,41 @@ int strreplace(std::string &str, const std::string& search, const std::string& r
namespace util {
/**
- * @fn double edit_distance(std::u32string const &lhs, std::u32string const &rhs)
+ * @fn bool streqlower(std::string_view str, std::string_view lcstr)
+ *
+ * @brief Tests whether a mixed-case string matches a lowercase string.
+ *
+ * @param [in] str First string to compare (may be mixed-case).
+ * @param [in] lcstr Second string to compare (must be all lowercase).
+ *
+ * @return True if the strings match regardless of case.
+ */
+
+bool streqlower(std::string_view str, std::string_view lcstr)
+{
+ return std::equal(str.begin(), str.end(), lcstr.begin(), lcstr.end(),
+ [] (unsigned char c1, unsigned char c2) { return std::tolower(c1) == c2; });
+}
+
+/**
+ * @fn bool strequpper(std::string_view str, std::string_view ucstr)
+ *
+ * @brief Tests whether a mixed-case string matches an uppercase string.
+ *
+ * @param [in] str First string to compare (may be mixed-case).
+ * @param [in] ucstr Second string to compare (must be all uppercase).
+ *
+ * @return True if the strings match regardless of case.
+ */
+
+bool strequpper(std::string_view str, std::string_view ucstr)
+{
+ return std::equal(str.begin(), str.end(), ucstr.begin(), ucstr.end(),
+ [] (unsigned char c1, unsigned char c2) { return std::toupper(c1) == c2; });
+}
+
+/**
+ * @fn double edit_distance(std::u32string_view lhs, std::u32string_view rhs)
*
* @brief Compares strings and returns prefix-weighted similarity score (smaller is more similar).
*
@@ -254,7 +235,7 @@ namespace util {
* @return Similarity score ranging from 0.0 (totally dissimilar) to 1.0 (identical).
*/
-double edit_distance(std::u32string const &lhs, std::u32string const &rhs)
+double edit_distance(std::u32string_view lhs, std::u32string_view rhs)
{
// based on Jaro-Winkler distance
// TODO: this breaks if the lengths don't fit in a long int, but that's not a big limitation
@@ -262,8 +243,8 @@ double edit_distance(std::u32string const &lhs, std::u32string const &rhs)
constexpr double PREFIX_WEIGHT(0.1);
constexpr double PREFIX_THRESHOLD(0.7);
- std::u32string const &longer((lhs.length() >= rhs.length()) ? lhs : rhs);
- std::u32string const &shorter((lhs.length() < rhs.length()) ? lhs : rhs);
+ std::u32string_view const &longer((lhs.length() >= rhs.length()) ? lhs : rhs);
+ std::u32string_view const &shorter((lhs.length() < rhs.length()) ? lhs : rhs);
// find matches
long const range((std::max)(long(longer.length() / 2) - 1, 0L));