Hi List,

attached is a patch that adds more 'const' modifiers to 'Octstr' and get 
better 'octstr' performance (some functions were hand-optimized but not all, 
means more work should be done;)). Also you can find some simple benchmarks 
in attached .txt file.

Comments and votes please!

-- 
Best regards / Mit besten Grüßen aus Düsseldorf

Dipl.-Ing.
Alexander Malysh
___________________________________________

Centrium GmbH
Vogelsanger Weg 80
40470 Düsseldorf

Fon: +49 (0211) 74 84 51 80
Fax: +49 (0211) 277 49 109

email: [EMAIL PROTECTED]
web: www.centrium.de
msn: [EMAIL PROTECTED]
icq: 98063111
___________________________________________

Please avoid sending me Word, Excel or PowerPoint attachments.
See http://www.fsf.org/philosophy/no-word-attachments.html
Index: gwlib/octstr.c
===================================================================
RCS file: /home/cvs/gateway/gwlib/octstr.c,v
retrieving revision 1.154
diff -a -u -r1.154 octstr.c
--- gwlib/octstr.c	2 Dec 2003 09:21:26 -0000	1.154
+++ gwlib/octstr.c	19 Jan 2004 11:53:43 -0000
@@ -142,6 +142,13 @@
  */
 #define CSTR_TO_LONG(ptr)	(((long) ptr) >> 2)
 
+
+/*
+ * HEX to ASCII
+ */
+#define H2B(a) (a >= '0' && a <= '9' ? a - '0' : (a >= 'a' && a <= 'f' ? a - 'a' + 10 : (a >= 'A' && a <= 'F' ? a - 'A' + 10 : -1)))
+
+
 /***********************************************************************
  * Declarations of internal functions. These are defined at the end of
  * the file.
@@ -174,6 +181,8 @@
     size++;   /* make room for the invisible terminating NUL */
 
     if (size > ostr->size) {
+        /* allways reallocate in 1kB chunks */
+        size += 1024 - (size % 1024);
         ostr->data = gw_realloc(ostr->data, size);
         ostr->size = size;
     }
@@ -325,7 +334,7 @@
 }
 
 
-Octstr *octstr_copy_real(Octstr *ostr, long from, long len, const char *file, long line,
+Octstr *octstr_copy_real(const Octstr *ostr, long from, long len, const char *file, long line,
                          const char *func)
 {
     seems_valid(ostr);
@@ -378,7 +387,7 @@
 }
 
 
-int octstr_get_char(Octstr *ostr, long pos)
+int octstr_get_char(const Octstr *ostr, long pos)
 {
     seems_valid(ostr);
     if (pos >= ostr->len || pos < 0)
@@ -440,7 +449,7 @@
 void octstr_binary_to_hex(Octstr *ostr, int uppercase)
 {
     unsigned char *hexits;
-    long i;
+    long i, tmp;
 
     seems_valid(ostr);
     gw_assert(!ostr->immutable);
@@ -454,8 +463,9 @@
      * overwriting the data while we read it.  Even the order of
      * the two assignments is important, to get i == 0 right. */
     for (i = ostr->len - 1; i >= 0; i--) {
-        ostr->data[i * 2 + 1] = hexits[ostr->data[i] % 16];
-        ostr->data[i * 2] = hexits[(ostr->data[i] / 16) & 0xf];
+        tmp = i << 1; /* tmp = i * 2; */
+        ostr->data[tmp + 1] = hexits[ostr->data[i] & 0xf];
+        ostr->data[tmp] = hexits[ostr->data[i] >> 4];
     }
 
     ostr->len = ostr->len * 2;
@@ -909,7 +919,20 @@
 }
 
 
-int octstr_search_char(Octstr *ostr, int ch, long pos)
+int octstr_str_ncompare(const Octstr *ostr, const char *str, long n)
+{
+    seems_valid(ostr);
+
+    if (str == NULL)
+        return -1;
+    if (ostr->data == NULL)
+        return 1; /* str grater */
+
+    return strncmp(ostr->data, str, n);
+}
+
+
+int octstr_search_char(const Octstr *ostr, int ch, long pos)
 {
     unsigned char *p;
 
@@ -928,7 +951,7 @@
 }
 
 
-int octstr_search_chars(Octstr *ostr, Octstr *chars, long pos)
+int octstr_search_chars(const Octstr *ostr, const Octstr *chars, long pos)
 {
     long i, j;
     for(i=0; i < octstr_len(chars); i++) {
@@ -940,7 +963,7 @@
 }
 
 
-int octstr_search(Octstr *haystack, Octstr *needle, long pos)
+int octstr_search(const Octstr *haystack, const Octstr *needle, long pos)
 {
     int first;
 
@@ -972,7 +995,7 @@
 }
 
 
-int octstr_case_search(Octstr *haystack, Octstr *needle, long pos)
+int octstr_case_search(const Octstr *haystack, const Octstr *needle, long pos)
 {
     long i, j;
     int c1, c2;
@@ -999,7 +1022,7 @@
     return -1;    
 }
 
-int octstr_case_nsearch(Octstr *haystack, Octstr *needle, long pos, long n)
+int octstr_case_nsearch(const Octstr *haystack, const Octstr *needle, long pos, long n)
 {
     long i, j;
     int c1, c2;
@@ -1139,7 +1162,7 @@
 }
 
 
-void octstr_insert(Octstr *ostr1, Octstr *ostr2, long pos)
+void octstr_insert(Octstr *ostr1, const Octstr *ostr2, long pos)
 {
     seems_valid(ostr1);
     seems_valid(ostr2);
@@ -1334,7 +1357,7 @@
 }
 
 
-void octstr_append(Octstr *ostr1, Octstr *ostr2)
+void octstr_append(Octstr *ostr1, const Octstr *ostr2)
 {
     gw_assert(ostr1 != NULL);
     octstr_insert(ostr1, ostr2, ostr1->len);
@@ -1432,7 +1455,7 @@
 }
 
 
-List *octstr_split_words(Octstr *ostr)
+List *octstr_split_words(const Octstr *ostr)
 {
     unsigned char *p;
     List *list;
@@ -1470,7 +1493,7 @@
 }
 
 
-List *octstr_split(Octstr *os, Octstr *sep)
+List *octstr_split(const Octstr *os, const Octstr *sep)
 {
     List *list;
     long next, pos, seplen;
@@ -1502,8 +1525,7 @@
     return octstr_case_compare(item, pattern) == 0;
 }
 
-
-void octstr_dump(Octstr *ostr, int level)
+void octstr_dump(const Octstr *ostr, int level)
 {
     unsigned char *p, *d, buf[1024], charbuf[256];
     long pos;
@@ -1604,61 +1626,56 @@
     octstr_dump(ostr, level + 1);
 }
 
+
 void octstr_url_encode(Octstr *ostr)
 {
-    int i, n, newlen;
-    unsigned char *str, *str2, *hexits;
-    unsigned char c;
-    Octstr *res;
+    long i, n, len;
+    unsigned char c, *str, *str2, *res, *hexits;
 
     seems_valid(ostr);
 
     if (ostr->immutable || ostr->len == 0)
-	return;
+        return;
 
-    res = octstr_create("");
-    str = ostr->data;
-    n = 0;
-    for (i = 0; i < ostr->len; i++)
+    /* calculate new length */
+    for (i = 0, str = ostr->data, n = 0; i < ostr->len; i++)
 	if (!is_safe[*str++])
 	    n++;
-    newlen = ostr->len + 2 * n;
-    res->len = newlen;
-    res->size = res->len + 1;
-    res->data = gw_malloc(res->size);
+
+    if (n == 0) /* we are done, all chars are safe */
+       return;
 
     hexits = "0123456789ABCDEF";
 
-    str = ostr->data;
-    str2 = res->data;
-    for (i = 0; i < ostr->len; i++) {
-	c = *str++;
-	if (!is_safe[c]) {
-	    *str2++ = '%';
-	    *str2++ = hexits[c >> 4 & 0xf];
-	    *str2++ = hexits[c & 0xf];
-	}
-	else if (c == ' ')
-	    *str2++ = '+';
-	else
-	    *str2++ = c;
+    res = str2 = gw_malloc((len = ostr->len + 2 * n + 1));
+
+    for (i = 0, str = ostr->data; i < ostr->len; i++) {
+        c = *str++;
+        if (!is_safe[c]) {
+            *str2++ = '%';
+            *str2++ = hexits[c >> 4 & 0xf];
+            *str2++ = hexits[c & 0xf];
+        }
+        else if (c == ' ')
+            *str2++ = '+';
+        else
+            *str2++ = c;
     }
     *str2 = 0;
-    seems_valid(res);
-    
-    octstr_truncate(ostr, 0);
-    octstr_insert(ostr, res, 0);
-    octstr_destroy(res);
+    gw_free(ostr->data);
+    ostr->data = res;
+    ostr->size = len;
+    ostr->len = len - 1;
+
+    seems_valid(ostr);
 }
 
 
 int octstr_url_decode(Octstr *ostr)
 {
-    long value;
     unsigned char *string = ostr->data;
     unsigned char *dptr = ostr->data;
-    unsigned char buf[3];    	/* buffer for strtol conversion */
-    buf[2] = '\0';
+    int code, code2, ret = 0;
 
     seems_valid(ostr);
     gw_assert(!ostr->immutable);
@@ -1668,39 +1685,40 @@
 
     do {
         if (*string == '%') {
-            if (*(string + 1) == '\0' || *(string + 2) == '\0')
-                goto error;
-            buf[0] = *(string + 1);
-            buf[1] = *(string + 2);
-            value = strtol(buf, NULL, 16);
-
-            if (value >= 0 && value < 256) {
-                *dptr = (unsigned char)value;
-                string += 3;
-                dptr++;
+            if (*(string + 1) == '\0' || *(string + 2) == '\0') {
+                warning(0, "octstr_url_decode: corrupted end-of-string <%s>", string);
+                ret = -1;
+                break;
+            }
+
+            code = H2B(*(string + 1));
+            code2 = H2B(*(string + 2));
+
+            if (code == -1 || code2 == -1) {
+                warning(0, "octstr_url_decode: garbage detected (%c%c%c) skipping.",
+                            *string, *(string + 1), *(string + 2));
+                *dptr++ = *string++;
+                *dptr++ = *string++;
+                *dptr++ = *string++;
+                ret = -1;
                 continue;
             }
-            warning(0, "Garbage encoded (value = %ld)", value);
+
+            *dptr++ = code << 4 | code2;
+            string += 3;
         }
-        if (*string == '+') {
+        else if (*string == '+') {
             *dptr++ = ' ';
             string++;
         } else
             *dptr++ = *string++;
     } while (*string); 	/* we stop here because it terimates encoded string */
-    *dptr = '\0';
-
-    ostr->len = (dptr - ostr->data);
-
-    seems_valid(ostr);
-    return 0;
 
-error:
     *dptr = '\0';
     ostr->len = (dptr - ostr->data);
-    warning(0, "octstr_url_decode: corrupted end-of-string <%s>", string);
+
     seems_valid(ostr);
-    return -1;
+    return ret;
 }
 
 
Index: gwlib/octstr.h
===================================================================
RCS file: /home/cvs/gateway/gwlib/octstr.h,v
retrieving revision 1.81
diff -a -u -r1.81 octstr.h
--- gwlib/octstr.h	2 Dec 2003 09:21:44 -0000	1.81
+++ gwlib/octstr.h	19 Jan 2004 11:53:43 -0000
@@ -173,7 +173,7 @@
  * octet string is created. If `from+len' is after the end of `ostr', 
  * `len' is reduced appropriately.
  */
-Octstr *octstr_copy_real(Octstr *ostr, long from, long len, const char *file,
+Octstr *octstr_copy_real(const Octstr *ostr, long from, long len, const char *file,
                          long line, const char *func);
 #define octstr_copy(ostr, from, len) \
     gw_claim_area(octstr_copy_real((ostr), (from), (len), __FILE__, __LINE__, __func__))
@@ -200,7 +200,7 @@
  * value has a range of 0..255 for valid positions, and -1 if `pos' is
  * after the end of the octet string.
  */
-int octstr_get_char(Octstr *ostr, long pos);
+int octstr_get_char(const Octstr *ostr, long pos);
 
 
 /*
@@ -332,6 +332,12 @@
 
 
 /*
+ * Same as octstr_str_compare, but comparing is done only up to n bytes.
+ */
+int octstr_str_ncompare(const Octstr *ostr, const char *str, long n);
+
+
+/*
  * Write contents of octet string to a file. Return -1 for error, 0 for OK.
  */
 int octstr_print(FILE *f, Octstr *ostr);
@@ -341,14 +347,14 @@
  * Search the character from octet string starting from position pos. Returns 
  * the position (index) of the char in string, -1 if not found.
  */
-int octstr_search_char(Octstr *ostr, int ch, long pos);
+int octstr_search_char(const Octstr *ostr, int ch, long pos);
 
 
 /*
  * Search several character from octet string starting from position pos. Returns 
  * the position (index) of the first char found in string, -1 if none was found.
  */
-int octstr_search_chars(Octstr *ostr, Octstr *chars, long pos);
+int octstr_search_chars(const Octstr *ostr, const Octstr *chars, long pos);
 
 
 /*
@@ -356,18 +362,18 @@
  * Return the start position (index) of 'needle' in 'haystack'.
  * Return -1 if not found.
  */
-int octstr_search(Octstr *haystack, Octstr *needle, long pos);
+int octstr_search(const Octstr *haystack, const Octstr *needle, long pos);
 
 
 /*
  * Like octstr_search, but ignores 8-bit byte case.
  */
-int octstr_case_search(Octstr *haystack, Octstr *needle, long pos);
+int octstr_case_search(const Octstr *haystack, const Octstr *needle, long pos);
 
 /*
  * Like octstr_case_search, but searchs only first n octets.
  */
-int octstr_case_nsearch(Octstr *haystack, Octstr *needle, long pos, long n);
+int octstr_case_nsearch(const Octstr *haystack, const Octstr *needle, long pos, long n);
 
 /*
  * Write contents of octet string to a file, in human readable form. 
@@ -402,7 +408,7 @@
  * Insert one octet string into another. `pos' gives the position
  * in `ostr1' where `ostr2' should be inserted.
  */
-void octstr_insert(Octstr *ostr1, Octstr *ostr2, long pos);
+void octstr_insert(Octstr *ostr1, const Octstr *ostr2, long pos);
 
 
 /*
@@ -429,7 +435,7 @@
 /*
  * Append a second octstr to the first.
  */
-void octstr_append(Octstr *ostr1, Octstr *ostr2);
+void octstr_append(Octstr *ostr1, const Octstr *ostr2);
 
 
 /*
@@ -497,14 +503,14 @@
  * Split an octet string into words at whitespace, and return a list
  * containing the new octet strings.
  */
-List *octstr_split_words(Octstr *ostr);
+List *octstr_split_words(const Octstr *ostr);
 
 
 /*
  * Split an octet string into substrings at every occurence of `sep'.
  * Return List with the substrings.
  */
-List *octstr_split(Octstr *os, Octstr *sep);
+List *octstr_split(const Octstr *os, const Octstr *sep);
 
 
 /*
@@ -522,7 +528,7 @@
 /*
  * Print debugging information about octet string.
  */
-void octstr_dump(Octstr *ostr, int level);
+void octstr_dump(const Octstr *ostr, int level);
 
 
 /*
1) 'octstr_grow' 1kB preallocation chunks:
test code:
    os = octstr_create("qwertzuiopüöä+#lkjhgfdsayxcvbnm,:-<'*`?=)(/&%$§\"!");
    for (i=0; i< 10000000; i++) {
        octstr_append_cstr(os, "as12shdfjshg");
    }
    octstr_destroy(os);
        w/ prealloc
real    0m3.117s
user    0m2.455s
sys     0m0.640s

real    0m3.133s
user    0m2.400s
sys     0m0.705s

real    0m3.123s
user    0m2.555s
sys     0m0.535s

real    0m3.119s
user    0m2.520s
sys     0m0.560s

real    0m3.124s
user    0m2.575s
sys     0m0.515s
        w/o prealloc
real    0m13.269s
user    0m6.490s
sys     0m4.155s

real    0m10.918s
user    0m6.380s
sys     0m4.235s

real    0m10.734s
user    0m6.510s
sys     0m4.135s

real    0m10.700s
user    0m6.485s
sys     0m4.120s

real    0m10.709s
user    0m6.455s
sys     0m4.175s


2) optimized 'octstr_binary_to_hex', not too much but...
test code: 
    os = octstr_create("qwertzuiopüöä+#lkjhgfdsayxcvbnm,:-<'*`?=)(/&%$§\"!");
    for (i=0; i< 1000000; i++) {
         octstr_binary_to_hex(os, 0);
         octstr_hex_to_binary(os);
    }
    octstr_destroy(os);

        w/ optimization
real    0m7.053s
user    0m6.970s
sys     0m0.010s

real    0m7.251s
user    0m6.950s
sys     0m0.050s

real    0m7.120s
user    0m6.960s
sys     0m0.010s

real    0m7.081s
user    0m6.975s
sys     0m0.020s

real    0m7.058s
user    0m6.980s
sys     0m0.010s
        w/o optimization
real    0m7.695s
user    0m7.600s
sys     0m0.025s

real    0m7.697s
user    0m7.610s
sys     0m0.000s

real    0m7.689s
user    0m7.585s
sys     0m0.040s

real    0m7.682s
user    0m7.595s
sys     0m0.015s

real    0m7.685s
user    0m7.580s
sys     0m0.030s

3) octstr_url_encode
    for (i=0; i < 1000000 ; i++) {
        os = octstr_create("akljhkajhksfjhakfsjöä#+ü'ß12090ß)(/&%$§");
        octstr_url_encode(os);
        octstr_destroy(os);
    }
        w/o optimization
real    0m2.862s
user    0m2.846s
sys     0m0.004s

real    0m2.871s
user    0m2.853s
sys     0m0.002s

real    0m2.871s
user    0m2.853s
sys     0m0.002s

real    0m2.881s
user    0m2.862s
sys     0m0.001s

real    0m2.902s
user    0m2.871s
sys     0m0.002s

        w/ optimization
real    0m1.884s
user    0m1.868s
sys     0m0.003s

real    0m1.891s
user    0m1.879s
sys     0m0.002s

real    0m1.900s
user    0m1.875s
sys     0m0.003s

real    0m1.884s
user    0m1.867s
sys     0m0.003s

real    0m1.881s
user    0m1.867s
sys     0m0.002s

4) octstr_url_decode
test code:
    os = octstr_create("akljhkajhksfjhakfsjöä#+ü'ß12090ß)(/&%$§");
    for (i=0; i < 1000000 ; i++) {
        octstr_url_encode(os);
        octstr_url_decode(os);
    }

        w/o optimization
real    0m2.241s
user    0m2.226s
sys     0m0.001s

real    0m2.247s
user    0m2.228s
sys     0m0.003s

real    0m2.240s
user    0m2.223s
sys     0m0.004s

real    0m2.247s
user    0m2.234s
sys     0m0.002s

real    0m2.244s
user    0m2.230s
sys     0m0.002s

        w/ optimization
real    0m1.147s
user    0m1.133s
sys     0m0.003s

real    0m1.131s
user    0m1.121s
sys     0m0.003s

real    0m1.128s
user    0m1.116s
sys     0m0.004s

real    0m1.136s
user    0m1.123s
sys     0m0.002s

real    0m1.138s
user    0m1.129s
sys     0m0.001s


5) octstr_format
test code:
    os1 = octstr_create("qwertzuiopüöä+#lkjhgfdsayxcvbnm,:-<'*`?=)(/&%$§\"!");
    for (i=0; i< 1000000; i++) {
         os = octstr_format("%s %s %d %E", "lsdfjshgdfjshgfsjhg", 
"kdfl238974jhwdfjhajshg", i, os1);
         octstr_destroy(os);
    }

        w/o opt.
real    0m25.285s
user    0m24.740s
sys     0m0.040s

real    0m25.097s
user    0m24.710s
sys     0m0.085s

real    0m25.088s
user    0m24.735s
sys     0m0.055s

real    0m25.520s
user    0m24.800s
sys     0m0.030s

real    0m25.092s
user    0m24.720s
sys     0m0.060s

        w/ opt.
real    0m20.296s
user    0m20.000s
sys     0m0.040s

real    0m20.290s
user    0m19.995s
sys     0m0.020s

real    0m20.487s
user    0m20.025s
sys     0m0.040s

real    0m20.288s
user    0m19.985s
sys     0m0.055s

real    0m20.284s
user    0m20.000s
sys     0m0.035s

Reply via email to