2012-10-25 [colin] 3.8.1cvs106
authorColin Leroy <colin@colino.net>
Thu, 25 Oct 2012 07:45:01 +0000 (07:45 +0000)
committerColin Leroy <colin@colino.net>
Thu, 25 Oct 2012 07:45:01 +0000 (07:45 +0000)
* src/common/utils.c
* src/common/utils.h
* src/textview.c
Avoid strlen() on inner loop in textview_make_clickable_parts*()
reduces cost of strcasestr() in textview_make_clickable_parts*()
from 30% to 15%. Patch by Igor Mammedov

ChangeLog
PATCHSETS
configure.ac
src/common/utils.c
src/common/utils.h
src/textview.c

index 60736b9..298ce34 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2012-10-25 [colin]     3.8.1cvs106
+
+       * src/common/utils.c
+       * src/common/utils.h
+       * src/textview.c
+               Avoid strlen() on inner loop in textview_make_clickable_parts*()
+               reduces cost of strcasestr() in textview_make_clickable_parts*()
+               from 30% to 15%. Patch by Igor Mammedov
+
 2012-10-25 [colin]     3.8.1cvs105
 
        * src/textview.c
index c2376f3..9b34efd 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.1.2.6 -r 1.1.2.7 src/advsearch.c;  ) > 3.8.1cvs103.patchset
 ( cvs diff -u -r 1.100.2.85 -r 1.100.2.86 AUTHORS;  cvs diff -u -r 1.96.2.249 -r 1.96.2.250 src/textview.c;  cvs diff -u -r 1.12.2.35 -r 1.12.2.36 src/textview.h;  cvs diff -u -r 1.1.2.81 -r 1.1.2.82 src/gtk/authors.h;  ) > 3.8.1cvs104.patchset
 ( cvs diff -u -r 1.96.2.250 -r 1.96.2.251 src/textview.c;  ) > 3.8.1cvs105.patchset
+( cvs diff -u -r 1.36.2.207 -r 1.36.2.208 src/common/utils.c;  cvs diff -u -r 1.20.2.82 -r 1.20.2.83 src/common/utils.h;  cvs diff -u -r 1.96.2.251 -r 1.96.2.252 src/textview.c;  ) > 3.8.1cvs106.patchset
index c6e1375..60bbc15 100644 (file)
@@ -12,7 +12,7 @@ MINOR_VERSION=8
 MICRO_VERSION=1
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=105
+EXTRA_VERSION=106
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
index 1e39043..6cb336c 100644 (file)
@@ -534,9 +534,15 @@ freeout:
 /* Similar to `strstr' but this function ignores the case of both strings.  */
 gchar *strcasestr(const gchar *haystack, const gchar *needle)
 {
-       register size_t haystack_len, needle_len;
+       size_t haystack_len = strlen(haystack);
+
+       return strncasestr(haystack, haystack_len, needle);
+}
+
+gchar *strncasestr(const gchar *haystack, gint haystack_len, const gchar *needle)
+{
+       register size_t needle_len;
 
-       haystack_len = strlen(haystack);
        needle_len   = strlen(needle);
 
        if (haystack_len < needle_len || needle_len == 0)
index df340e7..b701ae9 100644 (file)
@@ -309,6 +309,9 @@ gchar *strcrchomp   (gchar          *str);
 gint file_strip_crs    (const gchar    *file);
 gchar *strcasestr      (const gchar    *haystack,
                         const gchar    *needle);
+gchar *strncasestr     (const gchar    *haystack,
+                        gint            haystack_len,
+                        const gchar    *needle);
 gpointer my_memmem     (gconstpointer   haystack,
                         size_t          haystacklen,
                         gconstpointer   needle,
index c1f06e0..8dd8863 100644 (file)
@@ -1311,7 +1311,8 @@ static void textview_make_clickable_parts(TextView *textview,
        GtkTextView *text = GTK_TEXT_VIEW(textview->text);
        GtkTextBuffer *buffer = gtk_text_view_get_buffer(text);
        GtkTextIter iter;
-       gchar *mybuf = g_strdup(linebuf);
+       gint mybuf_len = strlen(linebuf);
+       gchar *mybuf = g_strndup(linebuf, mybuf_len);
        
        /* parse table - in order of priority */
        struct table {
@@ -1319,6 +1320,7 @@ static void textview_make_clickable_parts(TextView *textview,
 
                /* token search function */
                gchar    *(*search)     (const gchar *haystack,
+                                        gint  haystack_len,
                                         const gchar *needle);
                /* part parsing function */
                gboolean  (*parse)      (const gchar *start,
@@ -1332,14 +1334,14 @@ static void textview_make_clickable_parts(TextView *textview,
        };
 
        static struct table parser[] = {
-               {"http://",  strcasestr, get_uri_part,   make_uri_string},
-               {"https://", strcasestr, get_uri_part,   make_uri_string},
-               {"ftp://",   strcasestr, get_uri_part,   make_uri_string},
-               {"sftp://",  strcasestr, get_uri_part,   make_uri_string},
-               {"gopher://",strcasestr, get_uri_part,   make_uri_string},
-               {"www.",     strcasestr, get_uri_part,   make_http_string},
-               {"mailto:",  strcasestr, get_uri_part,   make_uri_string},
-               {"@",        strcasestr, get_email_part, make_email_string}
+               {"http://",  strncasestr, get_uri_part,   make_uri_string},
+               {"https://", strncasestr, get_uri_part,   make_uri_string},
+               {"ftp://",   strncasestr, get_uri_part,   make_uri_string},
+               {"sftp://",  strncasestr, get_uri_part,   make_uri_string},
+               {"gopher://",strncasestr, get_uri_part,   make_uri_string},
+               {"www.",     strncasestr, get_uri_part,   make_http_string},
+               {"mailto:",  strncasestr, get_uri_part,   make_uri_string},
+               {"@",        strncasestr, get_email_part, make_email_string}
        };
        const gint PARSE_ELEMS = sizeof parser / sizeof parser[0];
 
@@ -1354,25 +1356,30 @@ static void textview_make_clickable_parts(TextView *textview,
 
        if (!g_utf8_validate(linebuf, -1, NULL)) {
                g_free(mybuf);
-               mybuf = g_malloc(strlen(linebuf)*2 +1);
-               conv_localetodisp(mybuf, strlen(linebuf)*2 +1, linebuf);
+               mybuf = g_malloc(mybuf_len*2 +1);
+               conv_localetodisp(mybuf, mybuf_len*2 +1, linebuf);
+               mybuf_len = strlen(mybuf);
        }
 
        gtk_text_buffer_get_end_iter(buffer, &iter);
 
        /* parse for clickable parts, and build a list of begin and end positions  */
        for (n = 0; n < PARSE_ELEMS; n++) {
+               gint len = mybuf_len;
+               gint needle_len = strlen(parser[n].needle);
                for (walk = mybuf;;) {
-                       gchar *scanpos = parser[n].search(walk, parser[n].needle);
+                       gchar *scanpos = parser[n].search(walk, len, parser[n].needle);
                        if (scanpos) {
                                /* check if URI can be parsed */
                                if (parser[n].parse(walk, scanpos, &bp, &ep, hdr)
-                                               && (size_t) (ep - bp - 1) > strlen(parser[n].needle)) {
+                                               && (size_t) (ep - bp - 1) > needle_len) {
                                        ADD_TXT_POS(bp, ep, n);
+                                       len -= ep - walk;
                                        walk = ep;
-                               } else
-                                       walk = scanpos +
-                                               strlen(parser[n].needle);
+                               } else {
+                                       len -= (scanpos + needle_len) - walk;
+                                       walk = scanpos + needle_len;
+                               }
                        } else
                                break;
                }
@@ -1423,6 +1430,7 @@ static void textview_make_clickable_parts_later(TextView *textview,
        GtkTextBuffer *buffer = gtk_text_view_get_buffer(text);
        GtkTextIter start_iter, end_iter;
        gchar *mybuf;
+       gint mybuf_len;
        gint offset = 0;
        /* parse table - in order of priority */
        struct table {
@@ -1430,6 +1438,7 @@ static void textview_make_clickable_parts_later(TextView *textview,
 
                /* token search function */
                gchar    *(*search)     (const gchar *haystack,
+                                        gint  haystack_len,
                                         const gchar *needle);
                /* part parsing function */
                gboolean  (*parse)      (const gchar *start,
@@ -1443,13 +1452,13 @@ static void textview_make_clickable_parts_later(TextView *textview,
        };
 
        static struct table parser[] = {
-               {"http://",  strcasestr, get_uri_part,   make_uri_string},
-               {"https://", strcasestr, get_uri_part,   make_uri_string},
-               {"ftp://",   strcasestr, get_uri_part,   make_uri_string},
-               {"sftp://",  strcasestr, get_uri_part,   make_uri_string},
-               {"www.",     strcasestr, get_uri_part,   make_http_string},
-               {"mailto:",  strcasestr, get_uri_part,   make_uri_string},
-               {"@",        strcasestr, get_email_part, make_email_string}
+               {"http://",  strncasestr, get_uri_part,   make_uri_string},
+               {"https://", strncasestr, get_uri_part,   make_uri_string},
+               {"ftp://",   strncasestr, get_uri_part,   make_uri_string},
+               {"sftp://",  strncasestr, get_uri_part,   make_uri_string},
+               {"www.",     strncasestr, get_uri_part,   make_http_string},
+               {"mailto:",  strncasestr, get_uri_part,   make_uri_string},
+               {"@",        strncasestr, get_email_part, make_email_string}
        };
        const gint PARSE_ELEMS = sizeof parser / sizeof parser[0];
 
@@ -1468,18 +1477,23 @@ static void textview_make_clickable_parts_later(TextView *textview,
        offset = gtk_text_iter_get_offset(&start_iter);
 
        /* parse for clickable parts, and build a list of begin and end positions  */
+       mybuf_len = strlen(mybuf);
        for (n = 0; n < PARSE_ELEMS; n++) {
+               gint len = mybuf_len;
+               gint needle_len = strlen(parser[n].needle);
                for (walk = mybuf;;) {
-                       gchar *scanpos = parser[n].search(walk, parser[n].needle);
+                       gchar *scanpos = parser[n].search(walk, len, parser[n].needle);
                        if (scanpos) {
                                /* check if URI can be parsed */
                                if (parser[n].parse(walk, scanpos, &bp, &ep, FALSE)
-                                               && (size_t) (ep - bp - 1) > strlen(parser[n].needle)) {
+                                               && (size_t) (ep - bp - 1) > needle_len) {
                                        ADD_TXT_POS_LATER(bp, ep, n);
+                                       len -= ep - walk;
                                        walk = ep;
-                               } else
-                                       walk = scanpos +
-                                               strlen(parser[n].needle);
+                               } else {
+                                       len -= (scanpos + needle_len) - walk;
+                                       walk = scanpos + needle_len;
+                               }
                        } else
                                break;
                }