Mercurial > octave
changeset 25698:ac386820f2b6
Return true when strncmp matches, but number of characters exceeds strlen (bug #54373)
* NEWS: Announce change in behavior.
* oct-string.cc (strncmp, strncmpi): Change templates to check length of
strings against neff (N effective) which is the smaller of the actual string
length or N itself.
* strfns.cc: Add new BIST tests, marked as regressions, for this behavior.
Change existing BIST tests to pass.
* publish.m (is_publish_markup): New nested function replacing an anonymous
function. This version does not index past the length of the string when
checking if the N+1 character is a space.
author | Rik <rik@octave.org> |
---|---|
date | Wed, 25 Jul 2018 10:55:46 -0700 |
parents | 91f0416c2ba7 |
children | 825e1d0dfa8e |
files | NEWS libinterp/corefcn/strfns.cc liboctave/util/oct-string.cc scripts/miscellaneous/publish.m |
diffstat | 4 files changed, 58 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Fri Jul 27 18:15:17 2018 -0400 +++ b/NEWS Wed Jul 25 10:55:46 2018 -0700 @@ -10,6 +10,14 @@ with Matlab. Change all uses of "ascending" and "descending" in existing code to the new options. + ** The strncmp and strncmpi functions now return true if the two input + strings match, even though the number of characters specified by N + exceeds the string length. This behavior more closely matches + common sense and is Matlab compatible. Example: + + Octave 5.0 : strncmp ("abc", "abc", 100) => true + Previously : strncmp ("abc", "abc", 100) => false + ** Figure graphic objects have a new property "Number" which is read-only and will return the handle (number) of the figure. However, if the property "IntegerHandle" has been set to "off" then
--- a/libinterp/corefcn/strfns.cc Fri Jul 27 18:15:17 2018 -0400 +++ b/libinterp/corefcn/strfns.cc Wed Jul 25 10:55:46 2018 -0700 @@ -658,11 +658,13 @@ %!assert (strncmp ("abce", "aBc", 3), false) %!assert (strncmp (100, 100, 1), false) %!assert (strncmp ("abce", {"abcd", "bca", "abc"}, 3), logical ([1, 0, 1])) -%!assert (strncmp ("abc", {"abcd", "bca", "abc"}, 4), logical ([0, 0, 0])) +%!assert (strncmp ("abc", {"abcd", "bca", "abc"}, 4), logical ([0, 0, 1])) %!assert (strncmp ({"abcd", "bca", "abc"},"abce", 3), logical ([1, 0, 1])) %!assert (strncmp ({"abcd", "bca", "abc"},{"abcd", "bca", "abe"}, 3), logical ([1, 1, 0])) %!assert (strncmp ("abc", {"abcd", 10}, 2), logical ([1, 0])) +%!assert <*54373> (strncmp ("abc", "abc", 100)) + %!error strncmp () %!error strncmp ("abc", "def") */ @@ -733,6 +735,8 @@ /* %!assert (strncmpi ("abc123", "ABC456", 3), true) + +%!assert <*54373> (strncmpi ("abc", "abC", 100)) */ DEFUN (__native2unicode__, args, ,
--- a/liboctave/util/oct-string.cc Fri Jul 27 18:15:17 2018 -0400 +++ b/liboctave/util/oct-string.cc Wed Jul 25 10:55:46 2018 -0700 @@ -146,8 +146,13 @@ octave::string::strncmp (const T& str_a, const T& str_b, const typename T::size_type n) { - return (numel (str_a) >= n && numel (str_b) >= n - && str_data_cmp<T> (str_a.data (), str_b.data (), n)); + typename T::size_type neff; + auto len_a = numel (str_a); + auto len_b = numel (str_b); + neff = std::min (std::max (len_a, len_b), n); + + return (len_a >= neff && len_b >= neff + && str_data_cmp<T> (str_a.data (), str_b.data (), neff)); } template<typename T> @@ -155,8 +160,13 @@ octave::string::strncmp (const T& str_a, const typename T::value_type *str_b, const typename T::size_type n) { - return (numel (str_a) >= n && strlen<T> (str_b) >= n - && str_data_cmp<T> (str_a.data (), str_b, n)); + typename T::size_type neff; + auto len_a = numel (str_a); + auto len_b = strlen<T> (str_b); + neff = std::min (std::max (len_a, len_b), n); + + return (len_a >= neff && len_b >= neff + && str_data_cmp<T> (str_a.data (), str_b, neff)); } @@ -165,8 +175,13 @@ octave::string::strncmpi (const T& str_a, const T& str_b, const typename T::size_type n) { - return (numel (str_a) >= n && numel (str_b) >= n - && str_data_cmpi<T> (str_a.data (), str_b.data (), n)); + typename T::size_type neff; + auto len_a = numel (str_a); + auto len_b = numel (str_b); + neff = std::min (std::max (len_a, len_b), n); + + return (len_a >= neff && len_b >= neff + && str_data_cmpi<T> (str_a.data (), str_b.data (), neff)); } template<typename T> @@ -174,8 +189,13 @@ octave::string::strncmpi (const T& str_a, const typename T::value_type *str_b, const typename T::size_type n) { - return (numel (str_a) >= n && strlen<T> (str_b) >= n - && str_data_cmpi<T> (str_a.data (), str_b, n)); + typename T::size_type neff; + auto len_a = numel (str_a); + auto len_b = strlen<T> (str_b); + neff = std::min (std::max (len_a, len_b), n); + + return (len_a >= neff && len_b >= neff + && str_data_cmpi<T> (str_a.data (), str_b, neff)); }
--- a/scripts/miscellaneous/publish.m Fri Jul 27 18:15:17 2018 -0400 +++ b/scripts/miscellaneous/publish.m Wed Jul 25 10:55:46 2018 -0700 @@ -425,9 +425,23 @@ ## ## Checks line to have N "%" or "#" lines ## followed either by a space or end of string - is_publish_markup = @(cstr, N) ... - any (strncmp (char (cstr), {"%%%", "##"}, N)) ... - && ((length (char (cstr)) == N) || ((char (cstr))(N + 1) == " ")); + function r = is_publish_markup (cstr, N) + str = char (cstr); + + r = any (strncmp (str, {"%%%", "##"}, N)); + if (r) + len = length (str); + if (len == N) + r = true; + elseif (len > N && str(N+1) == " ") + r = true; + else + r = false; + endif + endif + + return; + endfunction ## Checks line of cellstring to be a paragraph line is_paragraph = @(cstr) is_publish_markup (cstr, 1); ## Checks line of cellstring to be a section headline