Index: subversion/libsvn_subr/svn_string.c =================================================================== --- subversion/libsvn_subr/svn_string.c (revision 11908) +++ subversion/libsvn_subr/svn_string.c (working copy) @@ -54,6 +54,54 @@ return new_area; } +static APR_INLINE svn_boolean_t +string_compare (const char *str1, + const char *str2, + apr_size_t len1, + apr_size_t len2) +{ + /* easy way out :) */ + if (len1 != len2) + return FALSE; + + /* now the strings must have identical lenghths */ + + if ((memcmp (str1, str2, len1)) == 0) + return TRUE; + else + return FALSE; +} + +static APR_INLINE apr_size_t +string_first_non_whitespace (const char *str, apr_size_t len) +{ + apr_size_t i; + + for (i = 0; i < len; i++) + { + if (! apr_isspace (str[i])) + return i; + } + + /* if we get here, then the string must be entirely whitespace */ + return len; +} + +static APR_INLINE apr_size_t +find_char_backward (const char *str, apr_size_t len, char ch) +{ + apr_size_t i = len; + + while (i != 0) + { + if (str[--i] == ch) + return i; + } + + /* char was not found, return len */ + return len; +} + /* svn_string functions */ @@ -146,16 +194,8 @@ svn_boolean_t svn_string_compare (const svn_string_t *str1, const svn_string_t *str2) { - /* easy way out :) */ - if (str1->len != str2->len) - return FALSE; - - /* now that we know they have identical lengths... */ - - if (memcmp (str1->data, str2->data, str1->len)) - return FALSE; - else - return TRUE; + return + string_compare (str1->data, str2->data, str1->len, str2->len); } @@ -163,33 +203,15 @@ apr_size_t svn_string_first_non_whitespace (const svn_string_t *str) { - apr_size_t i; - - for (i = 0; i < str->len; i++) - { - if (! apr_isspace (str->data[i])) - { - return i; - } - } - - /* if we get here, then the string must be entirely whitespace */ - return str->len; + return + string_first_non_whitespace (str->data, 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 find_char_backward (str->data, str->len, ch); } @@ -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; @@ -395,16 +418,7 @@ svn_stringbuf_compare (const svn_stringbuf_t *str1, const svn_stringbuf_t *str2) { - /* easy way out :) */ - if (str1->len != str2->len) - return FALSE; - - /* now that we know they have identical lengths... */ - - if (memcmp (str1->data, str2->data, str1->len)) - return FALSE; - else - return TRUE; + return string_compare (str1->data, str2->data, str1->len, str2->len); } @@ -412,18 +426,7 @@ apr_size_t svn_stringbuf_first_non_whitespace (const svn_stringbuf_t *str) { - apr_size_t i; - - for (i = 0; i < str->len; i++) - { - if (! apr_isspace (str->data[i])) - { - return i; - } - } - - /* if we get here, then the string must be entirely whitespace */ - return str->len; + return string_first_non_whitespace (str->data, str->len); } @@ -448,15 +451,7 @@ 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 find_char_backward (str->data, str->len, ch); } @@ -464,16 +459,7 @@ svn_string_compare_stringbuf (const svn_string_t *str1, const svn_stringbuf_t *str2) { - /* easy way out :) */ - if (str1->len != str2->len) - return FALSE; - - /* now that we know they have identical lengths... */ - - if (memcmp (str1->data, str2->data, str1->len)) - return FALSE; - else - return TRUE; + return string_compare (str1->data, str2->data, str1->len, str2->len); } Index: subversion/tests/libsvn_subr/string-test.c =================================================================== --- subversion/tests/libsvn_subr/string-test.c (revision 11908) +++ subversion/tests/libsvn_subr/string-test.c (working copy) @@ -445,7 +445,214 @@ return SVN_NO_ERROR; } +/* Helper function for checking correctness of find_char_backward */ +static svn_error_t * +test_find_char_backward (const char* data, + apr_size_t len, + char ch, + apr_size_t pos, + svn_boolean_t msg_only, + apr_pool_t *pool) +{ + apr_size_t i; + if (msg_only) + return SVN_NO_ERROR; + + a = svn_stringbuf_create (data, pool); + i = svn_stringbuf_find_char_backward (a, ch); + + if (i == pos) + return SVN_NO_ERROR; + else + return fail (pool, "test failed"); +} + +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); + + return + test_find_char_backward (a->data, a->len, ',', 4, msg_only, pool); +} + +static svn_error_t * +test14 (const char **msg, + svn_boolean_t msg_only, + apr_pool_t *pool) +{ + *msg = "find_char_backward; 0 case"; + + a = svn_stringbuf_create (",test test", pool); + + return + test_find_char_backward (a->data, a->len, ',', 0, msg_only, pool); +} + +static svn_error_t * +test15 (const char **msg, + svn_boolean_t msg_only, + apr_pool_t *pool) +{ + *msg = "find_char_backward; strlen - 1 case"; + + a = svn_stringbuf_create ("testing,", pool); + + return test_find_char_backward (a->data, + a->len, + ',', + a->len - 1, + msg_only, + pool); +} + +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); + + return + test_find_char_backward (a->data, a->len, ',', 0, msg_only, pool); +} + +static svn_error_t * +test17 (const char **msg, + svn_boolean_t msg_only, + apr_pool_t *pool) +{ + *msg = "find_char_backward; no occurence case"; + + a = svn_stringbuf_create ("test test test", pool); + + return test_find_char_backward (a->data, + a->len, + ',', + a->len, + msg_only, + pool); +} + +static svn_error_t * +test_first_non_whitespace (const char *str, + const apr_size_t pos, + svn_boolean_t msg_only, + apr_pool_t *pool) +{ + apr_size_t i; + + if (msg_only) + return SVN_NO_ERROR; + + a = svn_stringbuf_create (str, pool); + + i = svn_stringbuf_first_non_whitespace (a); + + if (i == pos) + return SVN_NO_ERROR; + else + return fail (pool, "test failed"); +} + +static svn_error_t * +test18 (const char **msg, + svn_boolean_t msg_only, + apr_pool_t *pool) +{ + *msg = "check whitespace removal; common case"; + + return test_first_non_whitespace (" \ttest", 4, msg_only, pool); +} + +static svn_error_t * +test19 (const char **msg, + svn_boolean_t msg_only, + apr_pool_t *pool) +{ + *msg = "check whitespace removal; no whitespace case"; + + return test_first_non_whitespace ("test", 0, msg_only, pool); +} + +static svn_error_t * +test20 (const char **msg, + svn_boolean_t msg_only, + apr_pool_t *pool) +{ + *msg = "check whitespace removal; all whitespace case"; + + return test_first_non_whitespace (" ", 3, msg_only, pool); +} + +static svn_error_t * +test21 (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 (" \ttest\t\t \t ", pool); + b = svn_stringbuf_create ("test", pool); + + svn_stringbuf_strip_whitespace (a); + + if (svn_stringbuf_compare (a, b) == TRUE) + return SVN_NO_ERROR; + else + return fail (pool, "test failed"); +} + +static svn_error_t * +test_string_compare (const char* str1, + const char* str2, + svn_boolean_t msg_only, + apr_pool_t *pool) +{ + if (msg_only) + return SVN_NO_ERROR; + + a = svn_stringbuf_create (str1, pool); + b = svn_stringbuf_create (str2, pool); + + return svn_stringbuf_compare (a, b); +} + +static svn_error_t * +test22 (const char **msg, + svn_boolean_t msg_only, + apr_pool_t *pool) +{ + *msg = "compare stringbufs; different lengths"; + + if (test_string_compare ("abc", "abcd", msg_only, pool) == FALSE) + return SVN_NO_ERROR; + else + return fail (pool, "test failed"); +} + +static svn_error_t * +test23 (const char **msg, + svn_boolean_t msg_only, + apr_pool_t *pool) +{ + *msg = "compare stringbufs; equal length, different content"; + + if (test_string_compare ("abc", "abb", msg_only, pool) == FALSE) + return SVN_NO_ERROR; + else + return fail (pool, "test failed"); +} + /* ==================================================================== If you add a new test to this file, update this array. @@ -469,5 +676,16 @@ 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_PASS (test16), + SVN_TEST_PASS (test17), + SVN_TEST_PASS (test18), + SVN_TEST_PASS (test19), + SVN_TEST_PASS (test20), + SVN_TEST_PASS (test21), + SVN_TEST_PASS (test22), + SVN_TEST_PASS (test23), SVN_TEST_NULL };