#438360: Replace str{,n}casestr and strcasecmp by qof_utf8_{substr_nocase,strcasecmp}.

The functions used did not work for non-ascii characters.  The new
implementations use g_utf8_casefold and g_utf8_normalize to improve case
insensitive searches and comparisons.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@16547 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Andreas Köhler
2007-10-03 01:18:13 +00:00
parent 0f802deebe
commit fcfb7bdb95
3 changed files with 50 additions and 32 deletions

View File

@@ -148,7 +148,7 @@ string_match_predicate (gpointer object,
ret = 1;
} else if (pdata->options == QOF_STRING_MATCH_CASEINSENSITIVE) {
if (strcasestr (s, pdata->matchstring))
if (qof_utf8_substr_nocase (s, pdata->matchstring))
ret = 1;
} else {

View File

@@ -36,33 +36,48 @@
static QofLogModule log_module = QOF_MOD_UTIL;
/* Search for str2 in first nchar chars of str1, ignore case.. Return
* pointer to first match, or null. */
gchar *
strncasestr(const guchar *str1, const guchar *str2, size_t len)
gboolean
qof_utf8_substr_nocase (const gchar *haystack, const gchar *needle)
{
while (*str1 && len--)
{
if (toupper(*str1) == toupper(*str2))
{
if (strncasecmp(str1,str2,strlen(str2)) == 0)
{
return (gchar *) str1;
}
}
str1++;
}
return NULL;
gchar *haystack_casefold, *haystack_normalized;
gchar *needle_casefold, *needle_normalized;
gchar *p;
gint offset;
g_return_val_if_fail (haystack && needle, FALSE);
haystack_casefold = g_utf8_casefold (haystack, -1);
haystack_normalized = g_utf8_normalize (haystack_casefold, -1,
G_NORMALIZE_ALL);
g_free (haystack_casefold);
needle_casefold = g_utf8_casefold (needle, -1);
needle_normalized = g_utf8_normalize (needle_casefold, -1, G_NORMALIZE_ALL);
g_free (needle_casefold);
p = strstr (haystack_normalized, needle_normalized);
g_free (haystack_normalized);
g_free (needle_normalized);
return p != NULL;
}
/* Search for str2 in str1, ignore case. Return pointer to first
* match, or null. */
gchar *
strcasestr(const gchar *str1, const gchar *str2)
gint
qof_utf8_strcasecmp (const gchar *da, const gchar *db)
{
size_t len = strlen (str1);
gchar * retval = strncasestr (str1, str2, len);
return retval;
gchar *da_casefold, *db_casefold;
gint retval;
g_return_val_if_fail (da != NULL, 0);
g_return_val_if_fail (db != NULL, 0);
da_casefold = g_utf8_casefold (da, -1);
db_casefold = g_utf8_casefold (db, -1);
retval = g_utf8_collate (da_casefold, db_casefold);
g_free (da_casefold);
g_free (db_casefold);
return retval;
}
gint
@@ -89,7 +104,7 @@ safe_strcasecmp (const gchar * da, const gchar * db)
{
if ((da) && (db)) {
if ((da) != (db)) {
gint retval = strcasecmp ((da), (db));
gint retval = qof_utf8_strcasecmp ((da), (db));
/* if strings differ, return */
if (retval) return retval;
}

View File

@@ -166,6 +166,16 @@ void qof_close (void);
/* **** Prototypes *********************************************/
/** Search for an occurence of the substring needle in the string
* haystack, ignoring case. Return TRUE if one is found or FALSE
* otherwise. */
gboolean qof_utf8_substr_nocase (const gchar *haystack, const gchar *needle);
/** Use g_utf8_casefold and g_utf8_collate to compare two utf8 strings,
* ignore case. Return < 0 if da compares before db, 0 if they compare
* equal, > 0 if da compares after db. */
gint qof_utf8_strcasecmp (const gchar *da, const gchar *db);
/** The safe_strcmp compares strings da and db the same way that strcmp()
does, except that either may be null. This routine assumes that
a non-null string is always greater than a null string.
@@ -201,13 +211,6 @@ gint safe_strcasecmp (const gchar * da, const gchar * db);
*/
gint null_strcmp (const gchar * da, const gchar * db);
/** Search for str2 in first nchar chars of str1, ignore case. Return
* pointer to first match, or null. These are just like that strnstr
* and the strstr functions, except that they ignore the case. */
extern gchar *strncasestr(const guchar *str1, const guchar *str2,
size_t len);
extern gchar *strcasestr(const gchar *str1, const gchar *str2);
/** The ultostr() subroutine is the inverse of strtoul(). It accepts a
* number and prints it in the indicated base. The returned string
* should be g_freed when done. */