You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by Jesper Louis Andersen <jl...@mongers.org> on 2004/11/14 13:43:05 UTC

[PATCH] Nitpick to libsvn_subr/svn_string.c

While reading through the source of svn_string.c I found a little,
tiny nitpick. *_find_char_backward uses a signed int i, because this
i will get negative in the for loop. The problem is the initial
assignment in the for-loop in svn_string.c a bit after line 444:

for (i = (str->len -1); i >= 0; i++)
...

Now, str->len is of type apr_size_t, which is unsigned. So running 
this on a string big enough makes i negative by a big amount and 
the for-loop never executes and returns str->len. This is wrong.

The patch simply works by making i an apr_size_t, increasing it
and making the calculation str->len - i instead. Note that str->len
is loop invariant and str->len - i can be common subexpression 
eliminated. Thus the performance drop should not be measureable.

svn_string_t and svn_stringbuf_t uses identical code for 
string_find_char_backwards. Furthermore the functions are pure.
Hoist common logic into a new function string_find_char_backwards().

Also, I changed a bit of memcmp's to check explicitly for == 0.
I am not sure if this is the projects standard practice.

While we are here, add tests to the string tests to ensure this
new behaviour is as the old behaviour was. Also add a test for
whitespace stripping a svn_stringbuf_t.

Patch follows. Passes (new) regression suite:


Index: subversion/libsvn_subr/svn_string.c
===================================================================
--- subversion/libsvn_subr/svn_string.c	(revision 11892)
+++ subversion/libsvn_subr/svn_string.c	(working copy)
@@ -71,6 +71,20 @@
   return new_string;
 }
 
+apr_size_t
+string_find_char_backward (const char *str, apr_size_t len, char ch)
+{
+  apr_size_t i;
+
+  for (i = 0; i <= len; i++)
+    {
+      if (str[len - i] == ch)
+        return (len - i);
+    }
+  
+  return len;
+}
+
 svn_string_t *
 svn_string_ncreate (const char *bytes, apr_size_t size, apr_pool_t *pool)
 {
@@ -152,10 +166,10 @@
 
   /* now that we know they have identical lengths... */
   
-  if (memcmp (str1->data, str2->data, str1->len))
-    return FALSE;
-  else
+  if ((memcmp (str1->data, str2->data, str1->len)) == 0)
     return TRUE;
+  else
+    return FALSE;
 }
 
 
@@ -177,22 +191,12 @@
   return str->len;
 }
 
-
 apr_size_t
 svn_string_find_char_backward (const svn_string_t *str, char ch)
 {
-  int i;        /* signed! */
-
-  for (i = (str->len - 1); i >= 0; i--)
-    {
-      if (str->data[i] == ch)
-        return i;
-    }
-
-  return str->len;
+  return string_find_char_backward(str->data, str->len, ch);
 }
 
-
 
 /* svn_stringbuf functions */
 
@@ -326,6 +330,7 @@
           {
             apr_size_t prev_size = str->blocksize;
             str->blocksize *= 2;
+	    /* check for apr_size_t overflow */
             if (prev_size > str->blocksize)
               {
                 str->blocksize = minimum_size;
@@ -401,10 +406,10 @@
 
   /* now that we know they have identical lengths... */
   
-  if (memcmp (str1->data, str2->data, str1->len))
-    return FALSE;
-  else
+  if ((memcmp (str1->data, str2->data, str1->len)) == 0)
     return TRUE;
+  else
+    return FALSE;
 }
 
 
@@ -448,18 +453,9 @@
 apr_size_t
 svn_stringbuf_find_char_backward (const svn_stringbuf_t *str, char ch)
 {
-  int i;        /* signed! */
-
-  for (i = (str->len - 1); i >= 0; i--)
-    {
-      if (str->data[i] == ch)
-        return i;
-    }
-
-  return str->len;
+  return string_find_char_backward (str->data, str->len, ch);
 }
 
-
 svn_boolean_t
 svn_string_compare_stringbuf (const svn_string_t *str1,
                               const svn_stringbuf_t *str2)
@@ -470,10 +466,10 @@
 
   /* now that we know they have identical lengths... */
 
-  if (memcmp (str1->data, str2->data, str1->len))
-    return FALSE;
-  else
+  if ((memcmp (str1->data, str2->data, str1->len)) == 0)
     return TRUE;
+  else
+    return FALSE;
 }
 
 
Index: subversion/tests/libsvn_subr/string-test.c
===================================================================
--- subversion/tests/libsvn_subr/string-test.c	(revision 11892)
+++ subversion/tests/libsvn_subr/string-test.c	(working copy)
@@ -56,9 +56,16 @@
 const char *phrase_1 = "hello, ";
 const char *phrase_2 = "a longish phrase of sorts, longer than 16 anyway";
 
+/* the position of the comma in phrase_2 */
+const apr_size_t phrase_2_comma_postion = 25;
 
 
+const char *phrase_3 = "test";
+const char *phrase_3_whitespace = "   \ttest\t\t   ";
 
+
+
+
 static svn_error_t *
 test1 (const char **msg, 
        svn_boolean_t msg_only,
@@ -445,7 +452,70 @@
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test13 (const char **msg,
+	svn_boolean_t msg_only,
+	apr_pool_t *pool)
+{
+  apr_size_t i;
 
+  *msg = "find a character backwards in a svn_stringbuf_t";
+
+  if (msg_only)
+    return SVN_NO_ERROR;
+
+  a = svn_stringbuf_create (phrase_2, pool);
+  i = svn_stringbuf_find_char_backward (a, ',');
+
+  if (i == phrase_2_comma_postion)
+    return SVN_NO_ERROR;
+  else
+    return fail (pool, "test failed");
+}
+  
+static svn_error_t *
+test14 (const char **msg,
+	svn_boolean_t msg_only,
+	apr_pool_t *pool)
+{
+  apr_size_t i;
+
+  *msg = "find a character backwards in a svn_string_t";
+
+  if (msg_only)
+    return SVN_NO_ERROR;
+
+  a = svn_string_create (phrase_2, pool);
+  i = svn_string_find_char_backward (a, ',');
+
+  if (i == phrase_2_comma_postion)
+    return SVN_NO_ERROR;
+  else
+    return fail (pool, "test failed");
+}
+
+static svn_error_t *
+test15 (const char **msg,
+	svn_boolean_t msg_only,
+	apr_pool_t *pool)
+{
+  *msg = "check that whitespace will be stripped correctly";
+
+  if (msg_only)
+    return SVN_NO_ERROR;
+
+  a = svn_stringbuf_create (phrase_3_whitespace, pool);
+  b = svn_stringbuf_create (phrase_3, pool);
+
+  svn_stringbuf_strip_whitespace(a);
+
+  if (svn_stringbuf_compare(a, b) == TRUE)
+    return SVN_NO_ERROR;
+  else
+    return fail (pool, "test failed");
+}
+  
+
 /*
    ====================================================================
    If you add a new test to this file, update this array.
@@ -469,5 +539,8 @@
     SVN_TEST_PASS (test10),
     SVN_TEST_PASS (test11),
     SVN_TEST_PASS (test12),
+    SVN_TEST_PASS (test13),
+    SVN_TEST_PASS (test14),
+    SVN_TEST_PASS (test15),
     SVN_TEST_NULL
   };

-- 
jlouis

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Re: [PATCH] Nitpick to libsvn_subr/svn_string.c

Posted by Julian Foad <ju...@btopenworld.com>.
Branko Čibej wrote:
> Julian Foad wrote:
>> Good, but why are we writing this function out long-hand and not just 
>> calling standard strrchr() and subtracting the start pointer from its 
[...]
> strrchr must scan the string forwards first, and must always scan the 

Oh yes - that's the bit I didn't think of.  Forget I said it.  :-)

- Julian

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Re: [PATCH] Nitpick to libsvn_subr/svn_string.c

Posted by Branko Čibej <br...@xbc.nu>.
Jesper Louis Andersen wrote:

>Quoting Branko ??ibej (brane@xbc.nu):
>  
>
>>Please please read the section in HACKING about writing log messages. 
>>    
>>
>
>Bleh, sorry for my ignorance.
>  
>
Ah, well... I decided to fix the remaining issues myself and committed 
this in r11978. Good work, but please pay attention to the following 
comments for next time.

>Indentation fixed,
>  
>
not everywhere...

>Diff reduced against trunk by insterting and removing newlines where
>  there were differences,
>Space inserted after function identifier, before () group,
>__ removed from code,
>static, APR_INLINE where applicable,
>first_non_whitespace*, and string_compare* functions common logic
>  hoisted into helper functions.
>More tests for all changed functions,
>Correct log message (hopefully).
>  
>
The log message is too verbose. You try to document the new functions in 
the log message, but that isn't necessary -- they should be documented 
in the code. I reduced you log message (although it's still a bit longer 
than optimal); please look at it and compare to what's written in HACKING.

>+static APR_INLINE svn_boolean_t
>+string_compare (const char *str1, 
>+                const char *str2, 
>  
>
You left trailing whitespace in a number of places, the first one right 
here. It's a small nit, but it's a nit.

>@@ -326,6 +348,7 @@
>           {
>             apr_size_t prev_size = str->blocksize;
>             str->blocksize *= 2;
>+	    /* check for apr_size_t overflow */
>             if (prev_size > str->blocksize)
>               {
>                 str->blocksize = minimum_size;
>  
>
Oops. There was a tab character on this line. This is a bigger nit than 
the trailing whitespace.

>+  return test_find_char_backward (a->data, 
>+                                   a->len, 
>+                                   ',', 
>+                                   a->len - 1, 
>+                                   msg_only,
>+                                   pool);
>  
>
The indentation is wrong here, and in several other places below. I hope 
I found them all.


All in all, great work, I especially appreciate all the new tests. Needs 
a wee bit more attention to detail, though... :-)

-- Brane



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Re: [PATCH] Nitpick to libsvn_subr/svn_string.c

Posted by Jesper Louis Andersen <jl...@mongers.org>.
Quoting Branko ??ibej (brane@xbc.nu):
> Please please read the section in HACKING about writing log messages. 

Bleh, sorry for my ignorance.

Indentation fixed,
Diff reduced against trunk by insterting and removing newlines where
  there were differences,
Space inserted after function identifier, before () group,
__ removed from code,
static, APR_INLINE where applicable,
first_non_whitespace*, and string_compare* functions common logic
  hoisted into helper functions.
More tests for all changed functions,
Correct log message (hopefully).

This time I tried to do what you said, log message and patch follows,
maybe it needs another round, but we are definitely getting much 
closer.


--- Log message
Cleanup of subversion/libsvn_subr/svn_string.c.

* subversion/libsvn_subr/svn_string.c
  (string_compare): New function with common code for comparing
    strings. No change in existing code.
  (string_first_non_whitespace): New function with common code for
    finding the first character which is not a whitespace character.
    No change in existing code.
  (find_char_backward): New function with common code for finding
    a given character in the string, searching backwards. Eliminates
    a signedness issue by using an unsigned counter and counting 
    downwards in the for-loop.
  (svn_string_compare, svn_stringbuf_compare,
   svn_string_compare_stringbuf): Use the new common function 
    string_compare for these 3 functions.
  (svn_string_first_non_whitespace, 
   svn_stringbuf_first_non_whitespace): Use the new common function
    string_first_non_whitespace for these 2 functions.
  (svn_string_find_char_backward,
   svn_stringbuf_find_char_backward): Use the new common function
    find_char_backward for these 2 functions.
  (svn_stringbuf_ensure): Add a comment to the place where the code
    checks for overflow of an apr_size_t to help readers of the code.

* subversion/tests/libsvn_subr/string-test.c
  (test_find_char_backward): New function, which calls 
    svn_stringbuf_find_char_backward on a string and checks if the
    position the character was found matches the expected value.
  (test13): Using test_find_char_backward, test the case where
    the character is in the middle of the string.
  (test14): Using test_find_char_backward, test the case where
    the character is in the very beginning of the string.
  (test15): Using test_find_char_backward, test the case where
    the character is in the end of the string.
  (test16): Using test_find_char_backward, test the case where
    the string has length 0.
  (test17): Using test_find_char_backward, test the case where
    the string doesn't contain the character we searched for.
  (test_first_non_whitespace): New function. Given a string and an
    expected position for the first non-whitespace character, check
    if the svn_stringbuf_first_non_whitespace agrees.
  (test18): Using test_first_non_whitespace, check the common case 
    where there is whitespace.
  (test19): Using test_first_non_whitespace, check the case where
    there is no whitespace.
  (test20): Using test_first_non_whitespace, check the case where
    all of the string is whitespace.
  (test21): Check the correctness of svn_stringbuf_strip_whitespace
    in the common case.
  (test_string_compare): New function. Given 2 strings, creates
    stringbuffers for these and compares them via 
    svn_stringbuf_compare, returning the outcome.
  (test22): Check that svn_stringbuf_compare fails on inputs with
    different lengths, by using test_stringbuf_compare.
  (test23): Check that svn_stringbuf_compare fails on inputs of
    equal length, but different content, by using 
    test_stringbuf_compare.
  (test_funcs[]): Updated with new tests.

---

-- 
jlouis

Re: [PATCH] Nitpick to libsvn_subr/svn_string.c

Posted by Branko Čibej <br...@xbc.nu>.
Jesper Louis Andersen wrote:

>Quoting Branko ??ibej (brane@xbc.nu):
>  
>
>>You misread what I posted. 
>>    
>>
>Oops!
>
>Yes, I see the point. Here is what I have done:
>
>First, I expanded the tests so we now test 5 equivalence classes:
>  * The character is in the middle of the string
>  * The character is at the very beginning of the string
>  * The character is at the very end of the string
>  * The character is not in the string at all
>  * The string has len 0
>  
>
Very good.

>Next, I verified that my implementation fails. It does ;)
>  
>
Heh.

>Then, I changed to your implementation, correctly this time, and
>  verified it works.
>  
>
Good.

>--- Log Message ---
>  
>
Please please read the section in HACKING about writing log messages. 
You can get good examples from the Subversion logs, e.g., by running

    svn log http://svn.collab.net/repos/svn/trunk/subversion/include

There are also still a few formatting probems in your patch. Please read 
the relevant sections in HACKING carefully, and try to match your style 
to the surrounding code.

Sorry if all this seems pedantic, but we really must insist on following 
our coding standatds, because it makes the code easier to read and 
maintain. Certainly it means that patch submissions are more work, but 
in the long run, a bit of coding discipline is all for the best. :-)

>Index: subversion/libsvn_subr/svn_string.c
>===================================================================
>--- subversion/libsvn_subr/svn_string.c	(revision 11892)
>+++ subversion/libsvn_subr/svn_string.c	(working copy)
>@@ -71,6 +71,21 @@
>   return new_string;
> }
> 
>+apr_size_t
>+string__find_char_backward (const char *str, apr_size_t len, char ch)
>  
>
As I said before, this function should be declared static. The name 
shouldn't contain a double underscore (that's reserved for non-static 
function that aren't exported from the library). I suggest

    static APR_INLINE apr_size_t
    find_char_backward (...


>Index: subversion/tests/libsvn_subr/string-test.c
>  
>
This file has the space before parens in function calls. You should 
follow the style in use by the file.

>@@ -57,8 +58,6 @@
> const char *phrase_2 = "a longish phrase of sorts, longer than 16 anyway";
> 
> 
>-
>-
>  
>
Don't make unnecessary whitespace changes, they just make the diff bigger.

> static svn_error_t *
> test1 (const char **msg, 
>        svn_boolean_t msg_only,
>@@ -445,7 +444,124 @@
>   return SVN_NO_ERROR;
> }
> 
>+/* Helper function for checking correctness of find_char_backward */
>+static svn_error_t *
>+test__find_char_backward(const char* data,  
>  
>
No double underscore in the name, and missing space before paren.

>+static svn_error_t *
>+test13 (const char **msg,
>+        svn_boolean_t msg_only,
>+        apr_pool_t *pool)
>+{
>+  *msg = "find_char_backward; middle case";
>+  a = svn_stringbuf_create("test, test", pool);
>  
>
Missing space before paren.

>+
>+  return
>+    test__find_char_backward(a->data, a->len, ',', 4, msg_only, pool);
>  
>
And here... I won't mention all the other places, there are too many.

>+static svn_error_t *
>+test16 (const char **msg,
>+        svn_boolean_t msg_only,
>+        apr_pool_t *pool)
>+{
>+  *msg = "find_char_backward; len = 0 case";
>+
>+  a = svn_stringbuf_create("", pool);
>+
>+  assert(svn_stringbuf_isempty(a));
>  
>
This assert is unnecessary. If after all the other tests in this file 
you still don't believe that svn_stringbuf_create with an empty string 
parameter works correctly, then add another test case for that.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Re: [PATCH] Nitpick to libsvn_subr/svn_string.c

Posted by Jesper Louis Andersen <jl...@mongers.org>.
Quoting Branko ??ibej (brane@xbc.nu):
> You misread what I posted. 

Oops!

Yes, I see the point. Here is what I have done:

First, I expanded the tests so we now test 5 equivalence classes:
  * The character is in the middle of the string
  * The character is at the very beginning of the string
  * The character is at the very end of the string
  * The character is not in the string at all
  * The string has len 0

Next, I verified that my implementation fails. It does ;)

Then, I changed to your implementation, correctly this time, and
  verified it works.

--- Log Message ---
Eliminate signedness problems of find_char_backward in string types

The functions svn_string_find_char_backward and 
svn_stringbuf_find_char_backward suffers from a signedness problem
when allocating very big strings. The signed counter will be 
initialized to a negative number and the search-loop will never
execute. This change alters the loop to a downward counting one
and makes the counter an apr_size_t, thus eliminating the signedness
problem.

Also, the change hoists common logic for the functions 
svn_string_find_char_backward and svn_stringbuf_find_char_backward
into a common function string__find_char_backward. 

Expanded the regression test suite with 5 equivalence classes for
svn_stringbuf_find_char_backward:

  * The character is in the middle of the string
  * The character is at the very beginning of the string
  * The character is at the very end of the string
  * The character is not in the string at all
  * The string has len 0

--- Log message ---

Patch attached.

-- 
jlouis

Re: [PATCH] Nitpick to libsvn_subr/svn_string.c

Posted by Branko Čibej <br...@xbc.nu>.
Jesper Louis Andersen wrote:

>Quoting Branko ??ibej (brane@xbc.nu):
>
>  
>
>>I guess we could argue backwards and forwards and produce numbers that 
>>support both positions, while compilers get smarter and smarter... but I 
>>don't think it's worth it. Let's just fix the signedness issue you 
>>found, and leave it at that.
>>    
>>
>
>New patch. With the changes you suggested.
>
>Beware that your
>
>while(i != 0)
>  { 
>    if (str[i--] == ch)
>      return i;
>...
>
>will not return the char at position i, but the char at position i-1
>due to the i--. The patch below for-loops it correctly (I, I love
>regression checks).
>  
>
You misread what I posted. I wrote "str[--i]", not "str[i--]", and the 
difference is crucial. Your change is wrong because a) the first 
character it checks is str[len], which is always 0, and b) it never 
checks str[0]. I propose you expand the tests, because none of them 
catches this bug.

Before fixing this, please read HACKING and post a log message along 
with the patch. Oh, also please fix the alignment of the paramters in 
test13, test14 and test15.

Keep trying, you're almost there. :-)

-- Brane



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Re: [PATCH] Nitpick to libsvn_subr/svn_string.c

Posted by Jesper Louis Andersen <jl...@mongers.org>.
Quoting Branko ??ibej (brane@xbc.nu):

> I guess we could argue backwards and forwards and produce numbers that 
> support both positions, while compilers get smarter and smarter... but I 
> don't think it's worth it. Let's just fix the signedness issue you 
> found, and leave it at that.

New patch. With the changes you suggested.

Beware that your

while(i != 0)
  { 
    if (str[i--] == ch)
      return i;
...

will not return the char at position i, but the char at position i-1
due to the i--. The patch below for-loops it correctly (I, I love
regression checks).

Index: subversion/libsvn_subr/svn_string.c
===================================================================
--- subversion/libsvn_subr/svn_string.c	(revision 11892)
+++ subversion/libsvn_subr/svn_string.c	(working copy)
@@ -71,6 +71,20 @@
   return new_string;
 }
 
+apr_size_t
+string_find_char_backward (const char *str, apr_size_t len, char ch)
+{
+  apr_size_t i;
+
+  for(i = len; i != 0; i--)
+    {
+      if (str[i] == ch)
+        return i;
+    }
+
+  return len;
+}
+
 svn_string_t *
 svn_string_ncreate (const char *bytes, apr_size_t size, apr_pool_t *pool)
 {
@@ -152,10 +166,10 @@
 
   /* now that we know they have identical lengths... */
   
-  if (memcmp (str1->data, str2->data, str1->len))
-    return FALSE;
-  else
+  if ((memcmp (str1->data, str2->data, str1->len)) == 0)
     return TRUE;
+  else
+    return FALSE;
 }
 
 
@@ -177,22 +191,12 @@
   return str->len;
 }
 
-
 apr_size_t
 svn_string_find_char_backward (const svn_string_t *str, char ch)
 {
-  int i;        /* signed! */
-
-  for (i = (str->len - 1); i >= 0; i--)
-    {
-      if (str->data[i] == ch)
-        return i;
-    }
-
-  return str->len;
+  return string_find_char_backward(str->data, str->len, ch);
 }
 
-
 
 /* svn_stringbuf functions */
 
@@ -326,6 +330,7 @@
           {
             apr_size_t prev_size = str->blocksize;
             str->blocksize *= 2;
+	    /* check for apr_size_t overflow */
             if (prev_size > str->blocksize)
               {
                 str->blocksize = minimum_size;
@@ -401,10 +406,10 @@
 
   /* now that we know they have identical lengths... */
   
-  if (memcmp (str1->data, str2->data, str1->len))
-    return FALSE;
-  else
+  if ((memcmp (str1->data, str2->data, str1->len)) == 0)
     return TRUE;
+  else
+    return FALSE;
 }
 
 
@@ -448,18 +453,9 @@
 apr_size_t
 svn_stringbuf_find_char_backward (const svn_stringbuf_t *str, char ch)
 {
-  int i;        /* signed! */
-
-  for (i = (str->len - 1); i >= 0; i--)
-    {
-      if (str->data[i] == ch)
-        return i;
-    }
-
-  return str->len;
+  return string_find_char_backward (str->data, str->len, ch);
 }
 
-
 svn_boolean_t
 svn_string_compare_stringbuf (const svn_string_t *str1,
                               const svn_stringbuf_t *str2)
@@ -470,10 +466,10 @@
 
   /* now that we know they have identical lengths... */
 
-  if (memcmp (str1->data, str2->data, str1->len))
-    return FALSE;
-  else
+  if ((memcmp (str1->data, str2->data, str1->len)) == 0)
     return TRUE;
+  else
+    return FALSE;
 }
 
 
Index: subversion/tests/libsvn_subr/string-test.c
===================================================================
--- subversion/tests/libsvn_subr/string-test.c	(revision 11892)
+++ subversion/tests/libsvn_subr/string-test.c	(working copy)
@@ -56,9 +56,16 @@
 const char *phrase_1 = "hello, ";
 const char *phrase_2 = "a longish phrase of sorts, longer than 16 anyway";
 
+/* the position of the comma in phrase_2 */
+const apr_size_t phrase_2_comma_postion = 25;
 
 
+const char *phrase_3 = "test";
+const char *phrase_3_whitespace = "   \ttest\t\t   ";
 
+
+
+
 static svn_error_t *
 test1 (const char **msg, 
        svn_boolean_t msg_only,
@@ -445,7 +452,71 @@
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+test13 (const char **msg,
+	svn_boolean_t msg_only,
+	apr_pool_t *pool)
+{
+  apr_size_t i;
 
+  *msg = "find a character backwards in a svn_stringbuf_t";
+
+  if (msg_only)
+    return SVN_NO_ERROR;
+
+  a = svn_stringbuf_create (phrase_2, pool);
+  i = svn_stringbuf_find_char_backward (a, ',');
+
+  printf("%i\n", i);
+  if (i == phrase_2_comma_postion)
+    return SVN_NO_ERROR;
+  else
+    return fail (pool, "test failed");
+}
+  
+static svn_error_t *
+test14 (const char **msg,
+	svn_boolean_t msg_only,
+	apr_pool_t *pool)
+{
+  apr_size_t i;
+
+  *msg = "find a character backwards in a svn_string_t";
+
+  if (msg_only)
+    return SVN_NO_ERROR;
+
+  a = svn_string_create (phrase_2, pool);
+  i = svn_string_find_char_backward (a, ',');
+
+  if (i == phrase_2_comma_postion)
+    return SVN_NO_ERROR;
+  else
+    return fail (pool, "test failed");
+}
+
+static svn_error_t *
+test15 (const char **msg,
+	svn_boolean_t msg_only,
+	apr_pool_t *pool)
+{
+  *msg = "check that whitespace will be stripped correctly";
+
+  if (msg_only)
+    return SVN_NO_ERROR;
+
+  a = svn_stringbuf_create (phrase_3_whitespace, pool);
+  b = svn_stringbuf_create (phrase_3, pool);
+
+  svn_stringbuf_strip_whitespace(a);
+
+  if (svn_stringbuf_compare(a, b) == TRUE)
+    return SVN_NO_ERROR;
+  else
+    return fail (pool, "test failed");
+}
+  
+
 /*
    ====================================================================
    If you add a new test to this file, update this array.
@@ -469,5 +540,8 @@
     SVN_TEST_PASS (test10),
     SVN_TEST_PASS (test11),
     SVN_TEST_PASS (test12),
+    SVN_TEST_PASS (test13),
+    SVN_TEST_PASS (test14),
+    SVN_TEST_PASS (test15),
     SVN_TEST_NULL
   };
-- 
jlouis

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Re: [PATCH] Nitpick to libsvn_subr/svn_string.c

Posted by Branko Čibej <br...@xbc.nu>.
Julian Foad wrote:

> Branko Čibej wrote:
>
>> Jesper Louis Andersen wrote:
>>
>>> The patch simply works by making i an apr_size_t, increasing it
>>> and making the calculation str->len - i instead. Note that str->len
>>> is loop invariant and str->len - i can be common subexpression 
>>> eliminated. Thus the performance drop should not be measureable.
>>>
>> Ah, but whilst "len - i" can be CSE'd, it cant' be avoided. You can 
>> avoid the slowdown by continuing to use a countdown loop but shifting 
>> the limits, thusly:
>
>
> Good, but why are we writing this function out long-hand and not just 
> calling standard strrchr() and subtracting the start pointer from its 
> result (if non-null)?  We can reasonably expect strrchr() to be 
> implemented efficiently for the platform on which it is running, and 
> it may do better than our generic version.

strrchr must scan the string forwards first, and must always scan the 
whole string. We already know the length of the string and can scan 
backwards and stop at the first occurrence of the character. Also, while 
strrchr could concievably optimise memory access by reading whole words 
at a time, in practice I don't think the difference would show up for 
short strings.

I guess we could argue backwards and forwards and produce numbers that 
support both positions, while compilers get smarter and smarter... but I 
don't think it's worth it. Let's just fix the signedness issue you 
found, and leave it at that.

-- Brane



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Re: [PATCH] Nitpick to libsvn_subr/svn_string.c

Posted by Julian Foad <ju...@btopenworld.com>.
Branko Čibej wrote:
> Jesper Louis Andersen wrote:
>> The patch simply works by making i an apr_size_t, increasing it
>> and making the calculation str->len - i instead. Note that str->len
>> is loop invariant and str->len - i can be common subexpression 
>> eliminated. Thus the performance drop should not be measureable.
>>
> Ah, but whilst "len - i" can be CSE'd, it cant' be avoided. You can 
> avoid the slowdown by continuing to use a countdown loop but shifting 
> the limits, thusly:

Good, but why are we writing this function out long-hand and not just calling 
standard strrchr() and subtracting the start pointer from its result (if 
non-null)?  We can reasonably expect strrchr() to be implemented efficiently 
for the platform on which it is running, and it may do better than our generic 
version.

- Julian

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

Re: [PATCH] Nitpick to libsvn_subr/svn_string.c

Posted by Branko Čibej <br...@xbc.nu>.
Jesper Louis Andersen wrote:

>While reading through the source of svn_string.c I found a little,
>tiny nitpick. *_find_char_backward uses a signed int i, because this
>i will get negative in the for loop. The problem is the initial
>assignment in the for-loop in svn_string.c a bit after line 444:
>
>for (i = (str->len -1); i >= 0; i++)
>  
>
Surely you mistyped that?

>...
>
>Now, str->len is of type apr_size_t, which is unsigned. So running 
>this on a string big enough makes i negative by a big amount and 
>the for-loop never executes and returns str->len. This is wrong.
>  
>
Yes. (Not that I'd ever expect strings to get so large, but correctness 
is nice.)

>The patch simply works by making i an apr_size_t, increasing it
>and making the calculation str->len - i instead. Note that str->len
>is loop invariant and str->len - i can be common subexpression 
>eliminated. Thus the performance drop should not be measureable.
>  
>
Ah, but whilst "len - i" can be CSE'd, it cant' be avoided. You can 
avoid the slowdown by continuing to use a countdown loop but shifting 
the limits, thusly:

    apr_size_t i = len;
    while (i != 0)
      {
        if (str[--i] == ch)
          return i;
      }
    return len;

>svn_string_t and svn_stringbuf_t uses identical code for 
>string_find_char_backwards. Furthermore the functions are pure.
>Hoist common logic into a new function string_find_char_backwards().
>  
>
That's fine. I'd put an APR_INLINE in the declaration, too, and make the 
function static.

>Also, I changed a bit of memcmp's to check explicitly for == 0.
>I am not sure if this is the projects standard practice.
>  
>
HACKING doesn't say, but I think we more or less do what you did.

>While we are here, add tests to the string tests to ensure this
>new behaviour is as the old behaviour was. Also add a test for
>whitespace stripping a svn_stringbuf_t.
>  
>
New tests are always nice. :-)

-- Brane



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org