/* I make bug fix for strrep which make un expected substitution for 2d matrix of character the way of sorting the matrix is the problem Example: c=["Hello World;"Goodbye World"] c= Hello World Goodbye World c(1) ans = H c(2) ans = G which means that the matrix sorted as a long 1d matrix ["HGWO..."]which is completely worng as the function can't make any replacement so I try to make a some change to strrep which to split the 2d char matrix into 2 matrices and add them so they became a two wright strings then make the replacement correctly. */ commit 2e6fe69c2aab56223e150d41e6cf8f35627719fe Author: abdelrhman323 Date: Sat Mar 21 23:35:13 2020 +0200 first patch by strrep bug report diff --git a/patch.txt b/patch.txt new file mode 100644 index 0000000..e5f1654 --- /dev/null +++ b/patch.txt @@ -0,0 +1,489 @@ +commit 0613258f6c114678b4b4dd55b8d7d700a027cad4 +Author: abdelrhman323 +Date: Sat Mar 21 23:25:28 2020 +0200 + + fix bug strreplace.txt + +diff --git a/strreplace.txt b/strreplace.txt +new file mode 100644 +index 0000000..56620f5 +--- /dev/null ++++ b/strreplace.txt +@@ -0,0 +1,477 @@ ++commit 8d7453e1896702e87318738b2f115d1e689fb2fc ++Author: abdelrhman323 ++Date: Sat Mar 21 22:55:17 2020 +0200 ++ ++ fix bug strreplace.cc ++ ++diff --git a/strreplace.cc b/strreplace.cc ++new file mode 100644 ++index 0000000..de3388e ++--- /dev/null +++++ b/strreplace.cc ++@@ -0,0 +1,465 @@ +++/* +++ +++ Copyright (C) 2009-2017 Jaroslav Hajek +++ Copyright (C) 2009-2010 VZLU Prague +++ +++ This file is part of Octave. +++ +++ Octave is free software; you can redistribute it and/or modify it +++ under the terms of the GNU General Public License as published by the +++ Free Software Foundation; either version 3 of the License, or (at your +++ option) any later version. +++ +++ Octave is distributed in the hope that it will be useful, but WITHOUT +++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +++ for more details. +++ +++ You should have received a copy of the GNU General Public License +++ along with Octave; see the file COPYING. If not, see +++ . +++ +++ */ +++ +++ #if defined (HAVE_CONFIG_H) +++ # include "config.h" +++ #endif +++ +++ #include +++ #include +++ #include +++ #include +++ #include "oct-locbuf.h" +++ #include "Cell.h" +++ #include "ov.h" +++ #include "defun.h" +++ #include "unwind-prot.h" +++ #include "errwarn.h" +++ #include "utils.h" +++ +++ +++ // This allows safe indexing with char. +++ // In C++, char may be (and often is) signed! +++ #define ORD(ch) static_cast(ch) +++ #define TABSIZE (std::numeric_limits::max () + 1) +++ +++ // This is the quick search algorithm, as described at +++ // http://www-igm.univ-mlv.fr/~lecroq/string/node19.html +++ static void +++ qs_preprocess (const Array& needle, +++ octave_idx_type *table) +++ { +++ const char *x = needle.data (); +++ octave_idx_type m = needle.numel (); +++ +++ for (octave_idx_type i = 0; i < TABSIZE; i++) +++ table[i] = m + 1; +++ for (octave_idx_type i = 0; i < m; i++) +++ table[ORD(x[i])] = m - i; +++ } +++ +++ static Array +++ qs_search (const Array& needle, +++ const Array& haystack, +++ const octave_idx_type *table, +++ bool overlaps = true) +++ { +++ const char *x = needle.data (); +++ octave_idx_type m = needle.numel (); +++ const char *y = haystack.data (); +++ octave_idx_type n = haystack.numel (); +++ +++ // We'll use deque because it typically has the most favorable properties for +++ // the operation we need. +++ std::deque accum; +++ if (m == 1) +++ { +++ // Looking for a single character. +++ for (octave_idx_type i = 0; i < n; i++) +++ { +++ if (y[i] == x[0]) +++ accum.push_back (i); +++ } +++ } +++ else if (m == 2) +++ { +++ // Two characters. +++ if (overlaps) +++ { +++ for (octave_idx_type i = 0; i < n-1; i++) +++ { +++ if (y[i] == x[0] && y[i+1] == x[1]) +++ accum.push_back (i); +++ } +++ } +++ else +++ { +++ for (octave_idx_type i = 0; i < n-1; i++) +++ { +++ if (y[i] == x[0] && y[i+1] == x[1]) +++ accum.push_back (i++); +++ } +++ } +++ } +++ else if (n >= m) +++ { +++ // General case. +++ octave_idx_type j = 0; +++ +++ if (overlaps) +++ { +++ while (j < n - m) +++ { +++ if (std::equal (x, x + m, y + j)) +++ accum.push_back (j); +++ j += table[ORD(y[j + m])]; +++ } +++ } +++ else +++ { +++ while (j < n - m) +++ { +++ if (std::equal (x, x + m, y + j)) +++ { +++ accum.push_back (j); +++ j += m; +++ } +++ else +++ j += table[ORD(y[j + m])]; +++ } +++ } +++ +++ if (j == n - m && std::equal (x, x + m, y + j)) +++ accum.push_back (j); +++ } +++ +++ octave_idx_type nmatch = accum.size (); +++ octave_idx_type one = 1; +++ Array result (dim_vector (std::min (one, nmatch), nmatch)); +++ octave_idx_type k = 0; +++ for (std::deque::const_iterator iter = accum.begin (); +++ iter != accum.end (); iter++) +++ { +++ result.xelem (k++) = *iter; +++ } +++ +++ return result; +++ } +++ +++ DEFUN (strfind, args, , +++ doc: /* -*- texinfo -*- +++ 152 @deftypefn {} {@var{idx} =} strfind (@var{str}, @var{pattern}) +++ @deftypefnx {} {@var{idx} =} strfind (@var{cellstr}, @var{pattern}) +++ @deftypefnx {} {@var{idx} =} strfind (@dots{}, "overlaps", @var{val}) +++ Search for @var{pattern} in the string @var{str} and return the starting +++ index of every such occurrence in the vector @var{idx}. +++ +++ If there is no such occurrence, or if @var{pattern} is longer than +++ @var{str}, or if @var{pattern} itself is empty, then @var{idx} is the empty +++ array @code{[]}. +++ +++ The optional argument @qcode{"overlaps"} determines whether the pattern +++ can match at every position in @var{str} (true), or only for unique +++ occurrences of the complete pattern (false). The default is true. +++ +++ If a cell array of strings @var{cellstr} is specified then @var{idx} is a +++ cell array of vectors, as specified above. +++ +++ Examples: +++ +++ @example +++ @group +++ strfind ("abababa", "aba") +++ @result{} [1, 3, 5] +++ +++ strfind ("abababa", "aba", "overlaps", false) +++ @result{} [1, 5] +++ +++ strfind (@{"abababa", "bebebe", "ab"@}, "aba") +++ @result{} +++ @{ +++ [1,1] = +++ +++ 1 3 5 +++ +++ [1,2] = [](1x0) +++ [1,3] = [](1x0) +++ @} +++ @end group +++ @end example +++ @seealso{findstr, strmatch, regexp, regexpi, find} +++ @end deftypefn */) +++ { +++ int nargin = args.length (); +++ +++ if (nargin != 4 && nargin != 2) +++ print_usage (); +++ +++ bool overlaps = true; +++ if (nargin == 4) +++ { +++ if (! args(2).is_string () || ! args(3).is_scalar_type ()) +++ error ("strfind: invalid optional arguments"); +++ +++ std::string opt = args(2).string_value (); +++ +++ if (opt == "overlaps") +++ overlaps = args(3).bool_value (); +++ else +++ error ("strfind: unknown option: %s", opt.c_str ()); +++ } +++ +++ octave_value retval; +++ +++ octave_value argstr = args(0); +++ octave_value argpat = args(1); +++ +++ if (argpat.is_string ()) +++ { +++ Array needle = argpat.char_array_value (); +++ OCTAVE_LOCAL_BUFFER (octave_idx_type, table, TABSIZE); +++ qs_preprocess (needle, table); +++ +++ if (argstr.is_string ()) +++ if (argpat.is_empty ()) +++ // Return a null matrix for null pattern for MW compatibility +++ retval = Matrix (); +++ else +++ retval = octave_value (qs_search (needle, +++ argstr.char_array_value (), +++ table, overlaps), +++ true, true); +++ else if (argstr.is_cell ()) +++ { +++ const Cell argsc = argstr.cell_value (); +++ Cell retc (argsc.dims ()); +++ octave_idx_type ns = argsc.numel (); +++ +++ for (octave_idx_type i = 0; i < ns; i++) +++ { +++ octave_value argse = argsc(i); +++ if (! argse.is_string ()) +++ error ("strfind: each element of CELLSTR must be a string"); +++ +++ if (argpat.is_empty ()) +++ retc(i) = Matrix (); +++ else +++ retc(i) = octave_value (qs_search (needle, +++ argse.char_array_value (), +++ table, overlaps), +++ true, true); +++ } +++ +++ retval = retc; +++ } +++ else +++ error ("strfind: first argument must be a string or cell array of strings"); +++ } +++ else if (argpat.is_cell ()) +++ retval = do_simple_cellfun (Fstrfind, "strfind", args); +++ else +++ error ("strfind: PATTERN must be a string or cell array of strings"); +++ +++ return retval; +++ } +++ +++ /* +++ %!assert (strfind ("abababa", "aba"), [1, 3, 5]) +++ %!assert (strfind ("abababa", "aba", "overlaps", false), [1, 5]) +++ %!assert (strfind ({"abababa", "bla", "bla"}, "a"), {[1, 3, 5, 7], 3, 3}) +++ %!assert (strfind ("Linux _is_ user-friendly. It just isn't ignorant-friendly or idiot-friendly.", "friendly"), [17, 50, 68]) +++ %!assert (strfind ("abc", ""), []) +++ %!assert (strfind ("abc", {"", "b", ""}), {[], 2, []}) +++ %!assert (strfind ({"abc", "def"}, ""), {[], []}) +++ +++ %!error strfind () +++ %!error strfind ("foo", "bar", 1) +++ %!error strfind ("foo", 100, "foobar", 1) +++ %!error strfind ({"A", 1}, "foo") +++ %!error strfind (100, "foo") +++ %!error strfind ("foo", 100) +++ */ +++ +++ static Array +++ qs_replace (const Array& str, const Array& pat, +++ const Array& rep, +++ const octave_idx_type *table, +++ bool overlaps = true) +++ { +++ Array ret = str; +++ +++ octave_idx_type siz = str.numel (); +++ octave_idx_type psiz = pat.numel (); +++ octave_idx_type rsiz = rep.numel (); +++ +++ if (psiz != 0) +++ { +++ // Look up matches, without overlaps. +++ const Array idx = qs_search (pat, str, table, overlaps); +++ octave_idx_type nidx = idx.numel (); +++ +++ if (nidx) +++ { +++ // Compute result size. +++ octave_idx_type retsiz; +++ if (overlaps) +++ { +++ retsiz = 0; +++ // OMG. Is this the "right answer" MW always looks for, or +++ // someone was just lazy? +++ octave_idx_type k = 0; +++ for (octave_idx_type i = 0; i < nidx; i++) +++ { +++ octave_idx_type j = idx(i); +++ if (j >= k) +++ retsiz += j - k; +++ retsiz += rsiz; +++ k = j + psiz; +++ } +++ +++ retsiz += siz - k; +++ } +++ else +++ retsiz = siz + nidx * (rsiz - psiz); +++ +++ if (retsiz == 0) +++ ret.clear (dim_vector (0, 0)); +++ else +++ { +++ ret.clear (dim_vector (1, retsiz)); +++ const char *src = str.data (); +++ const char *reps = rep.data (); +++ char *dest = ret.fortran_vec (); +++ +++ octave_idx_type k = 0; +++ for (octave_idx_type i = 0; i < nidx; i++) +++ { +++ octave_idx_type j = idx(i); +++ if (j >= k) +++ dest = std::copy (src + k, src + j, dest); +++ dest = std::copy (reps, reps + rsiz, dest); +++ k = j + psiz; +++ } +++ +++ std::copy (src + k, src + siz, dest); +++ } +++ } +++ } +++ +++ return ret; +++ } +++ +++ +++DEFUN (strrep, args, , +++ doc: /* -*- texinfo -*- +++ @deftypefn {} {@var{newstr} =} strrep (@var{str}, @var{ptn}, @var{rep}) +++ @deftypefnx {} {@var{newstr} =} strrep (@var{cellstr}, @var{ptn}, @var{rep}) +++ @deftypefnx {} {@var{newstr} =} strrep (@dots{}, "overlaps", @var{val}) +++ Replace all occurrences of the pattern @var{ptn} in the string @var{str} +++ with the string @var{rep} and return the result. +++ The optional argument @qcode{"overlaps"} determines whether the pattern +++ can match at every position in @var{str} (true), or only for unique +++ occurrences of the complete pattern (false). The default is true. +++ @var{s} may also be a cell array of strings, in which case the replacement +++ is done for each element and a cell array is returned. +++ Example: +++ @example +++ @group +++ strrep ("This is a test string", "is", "&%$") +++ @result{} "Th&%$ &%$ a test string" +++ @end group +++ @end example +++ +++ @seealso{regexprep, strfind, findstr} +++ @end deftypefn */) +++ +++{ +++ int nargin = args.length (); +++ +++ if (nargin != 3 && nargin != 5) +++ print_usage (); +++ +++ bool overlaps = true; +++ +++ if (nargin == 5) +++ { +++ if (! args(3).is_string () || ! args(4).is_scalar_type ()) +++ error ("strrep: invalid optional arguments"); +++ +++ std::string opt = args(3).string_value (); +++ if (opt == "overlaps") +++ overlaps = args(4).bool_value (); +++ else +++ error ("strrep: unknown option: %s", opt.c_str ()); +++ } +++ +++ octave_value retval; +++ +++ octave_value argstr = args(0); +++ octave_value argpat = args(1); +++ octave_value argrep = args(2); +++//trial bug fix for strrep +++ if (argpat.is_string () && argrep.is_string ()) +++ { +++ const Array pat = argpat.char_array_value (); +++ const Array rep = argrep.char_array_value (); +++ const Array str = argstr.char_array_value (); +++ const char *y = str.data (); +++ std::string a; +++ std::string b; +++ OCTAVE_LOCAL_BUFFER (octave_idx_type, table, TABSIZE); +++ qs_preprocess (pat, table); +++ +++ if (argstr.is_string ()){ +++ retval = qs_replace (argstr.char_array_value (), pat, rep, table, overlaps); +++ octave_idx_type np = argstr.numel (); +++ if(!overlaps){ +++ +++ for (octave_idx_type i = 1; i < np; i+=2) +++ { a[i] =y[i]; +++ b[i] =y[i+1]; +++ } +++ octave_value z; +++ z =a+b; +++ retval = qs_replace (z.char_array_value (), pat, rep, table, overlaps); +++ }} +++ else if (argstr.is_cell ()) +++ { +++ const Cell argsc = argstr.cell_value (); +++ Cell retc (argsc.dims ()); +++ octave_idx_type ns = argsc.numel (); +++ +++ for (octave_idx_type i = 0; i < ns; i++) +++ { +++ octave_value argse = argsc(i); +++ if (argse.is_string ()) +++ retc(i) = qs_replace (argse.char_array_value (), pat, rep, +++ table, overlaps); +++ else +++ error ("strrep: each element of S must be a string"); +++ } +++ +++ retval = retc; +++ } +++ else +++ error ("strrep: S must be a string or cell array of strings"); +++ } +++ else if (argpat.is_cell () || argrep.is_cell ()) +++ retval = do_simple_cellfun (Fstrrep, "strrep", args); +++ else +++ error ("strrep: PTN and REP arguments must be strings or cell arrays of strings"); +++ +++ return retval; +++ } +++ +++ +++ /* +++ %!assert (strrep ("This is a test string", "is", "&%$"), +++ %! "Th&%$ &%$ a test string") +++ %!assert (strrep ("abababc", "abab", "xyz"), "xyzxyzc") +++ %!assert (strrep ("abababc", "abab", "xyz", "overlaps", false), %!assert (size (strrep ("a", "a", "")), [0 0]) +++ %!error strrep () +++ %!error strrep ("foo", "bar", 3, 4) +++*/