# HG changeset patch # User Jaroslav Hajek # Date 1262935665 -3600 # Node ID 5e2b4b7967cc3334200ac4e2914081eb93ac79ed # Parent dcde57cb5778a61de4af3bc053a3d2827ec032ae allow array of strings in strrep diff -r dcde57cb5778 -r 5e2b4b7967cc src/ChangeLog --- a/src/ChangeLog Thu Jan 07 17:26:18 2010 -0500 +++ b/src/ChangeLog Fri Jan 08 08:27:45 2010 +0100 @@ -1,3 +1,8 @@ +2010-01-08 Jaroslav Hajek + + * DLD-FUNCTIONS/strfind.cc (qs_replace): New function. + (Fstrrep): Use it here. Allow S to be a cellstr. + 2010-01-07 John W. Eaton * data.cc (cputime): Eliminate Windows-specific code. diff -r dcde57cb5778 -r 5e2b4b7967cc src/DLD-FUNCTIONS/strfind.cc --- a/src/DLD-FUNCTIONS/strfind.cc Thu Jan 07 17:26:18 2010 -0500 +++ b/src/DLD-FUNCTIONS/strfind.cc Fri Jan 08 08:27:45 2010 +0100 @@ -38,12 +38,13 @@ // This allows safe indexing with char. In C++, char may be (and often is) signed! #define ORD(ch) static_cast(ch) +#define TABSIZE (UCHAR_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[UCHAR_MAX]) + octave_idx_type table[TABSIZE]) { const char *x = needle.data (); octave_idx_type m = needle.numel (); @@ -58,7 +59,7 @@ static Array qs_search (const Array& needle, const Array& haystack, - const octave_idx_type table[UCHAR_MAX], + const octave_idx_type table[TABSIZE], bool overlaps = true) { const char *x = needle.data (); @@ -206,6 +207,45 @@ */ +static Array +qs_replace (const Array& str, const Array& pat, + const Array& rep, + const octave_idx_type table[TABSIZE]) +{ + Array ret = str; + + octave_idx_type siz = str.numel (), psiz = pat.numel (), rsiz = rep.numel (); + + if (psiz != 0) + { + // Look up matches, without overlaps. + const Array idx = qs_search (pat, str, table, false); + octave_idx_type nidx = idx.numel (); + + if (nidx) + { + // Compute result size. + octave_idx_type retsiz = siz + nidx * (rsiz - psiz); + ret.clear (dim_vector (1, retsiz)); + const char *src = str.data (), *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); + 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_DLD (strrep, args, , "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {} strrep (@var{s}, @var{x}, @var{y})\n\ @@ -218,6 +258,9 @@ @result{} \"Th&%$ &%$ a test string\"\n\ @end group\n\ @end example\n\ +\n\ +@var{s} may also be a cell array of strings, in which case the replacement is\n\ +done for each element and a cell array is returned.\n\ @seealso{regexprep, strfind, findstr}\n\ @end deftypefn") { @@ -227,49 +270,41 @@ if (nargin == 3) { octave_value argstr = args(0), argp = args(1), argr = args(2); - if (argp.is_string () && argp.is_string () && argr.is_string ()) + if (argp.is_string () && argr.is_string ()) { - const Array str = argstr.char_array_value (); const Array pat = argp.char_array_value (); const Array rep = argr.char_array_value (); - Array ret = str; + + OCTAVE_LOCAL_BUFFER (octave_idx_type, table, UCHAR_MAX); + qs_preprocess (pat, table); - octave_idx_type siz = str.numel (), psiz = pat.numel (), rsiz = rep.numel (); - - if (psiz != 0) + if (argstr.is_string ()) + retval = qs_replace (argstr.char_array_value (), pat, rep, table); + else if (argstr.is_cell ()) { - OCTAVE_LOCAL_BUFFER (octave_idx_type, table, UCHAR_MAX); - qs_preprocess (pat, table); + const Cell argsc = argstr.cell_value (); + Cell retc (argsc.dims ()); + octave_idx_type ns = argsc.numel (); - // Look up matches, without overlaps. - const Array idx = qs_search (pat, str, table, false); - octave_idx_type nidx = idx.numel (); - - if (nidx) + for (octave_idx_type i = 0; i < ns; i++) { - // Compute result size. - octave_idx_type retsiz = siz + nidx * (rsiz - psiz); - ret.clear (dim_vector (1, retsiz)); - const char *src = str.data (), *reps = rep.data (); - char *dest = ret.fortran_vec (); - - octave_idx_type k = 0; - for (octave_idx_type i = 0; i < nidx; i++) + octave_value argse = argsc(i); + if (argse.is_string ()) + retc(i) = qs_replace (argse.char_array_value (), pat, rep, table); + else { - octave_idx_type j = idx(i); - dest = std::copy (src + k, src + j, dest); - dest = std::copy (reps, reps + rsiz, dest); - k = j + psiz; + error ("strrep: each cell element must be a string"); + break; } + } - std::copy (src + k, src + siz, dest); - } + retval = retc; } - - retval = ret; + else + error ("strrep: first argument must be a string or cell array of strings"); } else - error ("strrep: all arguments must be strings"); + error ("strrep: 2rd and 3rd arguments must be strings"); } else print_usage ();