summaryrefslogtreecommitdiff
path: root/src/core/wee-string.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/wee-string.c')
-rw-r--r--src/core/wee-string.c123
1 files changed, 108 insertions, 15 deletions
diff --git a/src/core/wee-string.c b/src/core/wee-string.c
index 3c258ec94..391d23db3 100644
--- a/src/core/wee-string.c
+++ b/src/core/wee-string.c
@@ -394,6 +394,97 @@ string_toupper (const char *string)
}
/*
+ * Compares two chars (case sensitive).
+ *
+ * Returns: arithmetic result of subtracting the first char in string2
+ * from the first char in string1:
+ * < 0: string1 < string2
+ * 0: string1 == string2
+ * > 0: string1 > string2
+ */
+
+int
+string_charcmp (const char *string1, const char *string2)
+{
+ return utf8_char_int (string1) - utf8_char_int (string2);
+}
+
+/*
+ * Compares two chars (case insensitive).
+ *
+ * Returns: arithmetic result of subtracting the first char in string2
+ * (converted to lowercase) from the first char in string1 (converted
+ * to lowercase):
+ * < 0: string1 < string2
+ * 0: string1 == string2
+ * > 0: string1 > string2
+ */
+
+int
+string_charcasecmp (const char *string1, const char *string2)
+{
+ wint_t wchar1, wchar2;
+
+ /*
+ * optimization for single-byte chars: only letters A-Z must be converted
+ * to lowercase; this is faster than calling `towlower`
+ */
+ if (string1 && !((unsigned char)(string1[0]) & 0x80)
+ && string2 && !((unsigned char)(string2[0]) & 0x80))
+ {
+ wchar1 = string1[0];
+ if ((wchar1 >= 'A') && (wchar1 <= 'Z'))
+ wchar1 += ('a' - 'A');
+ wchar2 = string2[0];
+ if ((wchar2 >= 'A') && (wchar2 <= 'Z'))
+ wchar2 += ('a' - 'A');
+ }
+ else
+ {
+ wchar1 = towlower (utf8_char_int (string1));
+ wchar2 = towlower (utf8_char_int (string2));
+ }
+
+ return wchar1 - wchar2;
+}
+
+/*
+ * Compares two chars (case insensitive using a range).
+ *
+ * The range is the number of chars which can be converted from upper to lower
+ * case. For example 26 = all letters of alphabet, 29 = all letters + 3 chars.
+ *
+ * Examples:
+ * - range = 26: A-Z ==> a-z
+ * - range = 29: A-Z [ \ ] ==> a-z { | }
+ * - range = 30: A-Z [ \ ] ^ ==> a-z { | } ~
+ * (ranges 29 and 30 are used by some protocols like IRC)
+ *
+ * Returns: arithmetic result of subtracting the last compared char in string2
+ * (converted to lowercase) from the last compared char in string1 (converted
+ * to lowercase):
+ * < 0: string1 < string2
+ * 0: string1 == string2
+ * > 0: string1 > string2
+ */
+
+int
+string_charcasecmp_range (const char *string1, const char *string2, int range)
+{
+ wchar_t wchar1, wchar2;
+
+ wchar1 = utf8_char_int (string1);
+ if ((wchar1 >= (wchar_t)'A') && (wchar1 < (wchar_t)('A' + range)))
+ wchar1 += ('a' - 'A');
+
+ wchar2 = utf8_char_int (string2);
+ if ((wchar2 >= (wchar_t)'A') && (wchar2 < (wchar_t)('A' + range)))
+ wchar2 += ('a' - 'A');
+
+ return wchar1 - wchar2;
+}
+
+/*
* Compares two strings (case insensitive).
*
* Returns: arithmetic result of subtracting the last compared char in string2
@@ -411,7 +502,7 @@ string_strcasecmp (const char *string1, const char *string2)
while (string1 && string1[0] && string2 && string2[0])
{
- diff = utf8_charcasecmp (string1, string2);
+ diff = string_charcasecmp (string1, string2);
if (diff != 0)
return diff;
@@ -419,7 +510,7 @@ string_strcasecmp (const char *string1, const char *string2)
string2 = utf8_next_char (string2);
}
- return utf8_charcasecmp (string1, string2);
+ return string_charcasecmp (string1, string2);
}
/*
@@ -449,7 +540,7 @@ string_strcasecmp_range (const char *string1, const char *string2, int range)
while (string1 && string1[0] && string2 && string2[0])
{
- diff = utf8_charcasecmp_range (string1, string2, range);
+ diff = string_charcasecmp_range (string1, string2, range);
if (diff != 0)
return diff;
@@ -457,7 +548,7 @@ string_strcasecmp_range (const char *string1, const char *string2, int range)
string2 = utf8_next_char (string2);
}
- return utf8_charcasecmp_range (string1, string2, range);
+ return string_charcasecmp_range (string1, string2, range);
}
/*
@@ -479,7 +570,7 @@ string_strncasecmp (const char *string1, const char *string2, int max)
count = 0;
while ((count < max) && string1 && string1[0] && string2 && string2[0])
{
- diff = utf8_charcasecmp (string1, string2);
+ diff = string_charcasecmp (string1, string2);
if (diff != 0)
return diff;
@@ -491,7 +582,7 @@ string_strncasecmp (const char *string1, const char *string2, int max)
if (count >= max)
return 0;
else
- return utf8_charcasecmp (string1, string2);
+ return string_charcasecmp (string1, string2);
}
/*
@@ -523,7 +614,7 @@ string_strncasecmp_range (const char *string1, const char *string2, int max,
count = 0;
while ((count < max) && string1 && string1[0] && string2 && string2[0])
{
- diff = utf8_charcasecmp_range (string1, string2, range);
+ diff = string_charcasecmp_range (string1, string2, range);
if (diff != 0)
return diff;
@@ -535,7 +626,7 @@ string_strncasecmp_range (const char *string1, const char *string2, int max,
if (count >= max)
return 0;
else
- return utf8_charcasecmp_range (string1, string2, range);
+ return string_charcasecmp_range (string1, string2, range);
}
/*
@@ -572,13 +663,14 @@ string_strcmp_ignore_chars (const char *string1, const char *string2,
if (!string1 || !string1[0] || !string2 || !string2[0])
{
return (case_sensitive) ?
- utf8_charcmp (string1, string2) :
- utf8_charcasecmp (string1, string2);
+ string_charcmp (string1, string2) :
+ string_charcasecmp (string1, string2);
}
/* look at diff */
diff = (case_sensitive) ?
- utf8_charcmp (string1, string2) : utf8_charcasecmp (string1, string2);
+ string_charcmp (string1, string2) :
+ string_charcasecmp (string1, string2);
if (diff != 0)
return diff;
@@ -596,7 +688,8 @@ string_strcmp_ignore_chars (const char *string1, const char *string2,
}
}
return (case_sensitive) ?
- utf8_charcmp (string1, string2) : utf8_charcasecmp (string1, string2);
+ string_charcmp (string1, string2) :
+ string_charcasecmp (string1, string2);
}
/*
@@ -1984,7 +2077,7 @@ string_translate_chars (const char *string,
ptr_chars2 = chars2;
while (ptr_chars1 && ptr_chars1[0] && ptr_chars2 && ptr_chars2[0])
{
- if (utf8_charcmp (ptr_chars1, ptr_string) == 0)
+ if (string_charcmp (ptr_chars1, ptr_string) == 0)
{
string_dyn_concat (result, ptr_chars2, utf8_char_size (ptr_chars2));
translated = 1;
@@ -3736,7 +3829,7 @@ string_is_command_char (const char *string)
while (ptr_command_chars && ptr_command_chars[0])
{
- if (utf8_charcmp (ptr_command_chars, string) == 0)
+ if (string_charcmp (ptr_command_chars, string) == 0)
return 1;
ptr_command_chars = utf8_next_char (ptr_command_chars);
}
@@ -3798,7 +3891,7 @@ string_input_for_buffer (const char *string)
return string;
/* check if first char is doubled: if yes, then it's not a command */
- if (utf8_charcmp (string, next_char) == 0)
+ if (string_charcmp (string, next_char) == 0)
return next_char;
/* string is a command */