## Copyright (C) 2017 Sahil Yadav
## 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
## <http://www.gnu.org/licenses/>.

## -*- texinfo -*-
## @deftypefn  {} {@var{s} =} erase (@var{str}, @var{match})
## Delete all occurances of @var{match} within @var{str}
##
## @var{str} and @var{match} can be cell array of strings or a char vector
##
## If @var{str} is char vector, a char vector is returned containing string
## @var{str} remaining after the deletion of @var{match} from it.
##
## If @var{str} is cell array of strings, the returned value is the cell array
## of string @var{match} with substrings in cell array (or char vector) of
## @var{match} deleted from each of the strings of @var{str}.
##
## Unlike MATLAB @var{match}  cannot be an array of char vectors, if you are
## trying to run a file written for MATLAB, then just put @{@} around @var{match}
## and it shoud work in octave. If @var{str} is an array of char vectors then
## some trailing spaces might change. You should change it to a cell array.
##
## @example
## @group
## erase ('hello, world',' world')
##      @result{} 'hello,'
##
## erase (@{'octave';'octave is';'fabulous'@}, 'oct')
##      @result{} @{ave';'ave is';'fabulou'@}
##
## erase (@{'octave';'octave is';'fabulous'@}, @{'oct';'ous';'is'@})
##      @result{} @{'ave';'ave ';'fabul'@}
##
## erase ('supercalifragilisticexpialidocious', @{'cali';'exp';'ous'@})
##      @result{} 'superfragilisticialidoci'
##
## @end group
## @end example
##
## @seealso{strrep}
## @end deftypefn

## Author: Sahil Yadav <yadavsahil5198@gmail.com>


function finalstring = erase (str, match)

  if(nargin != 2 || ! ((ischar (str) && isvector (str))
                 || iscellstr (str) || ischar (str))
                 || ! ((ischar (match) && isvector (match))
                 || iscellstr (match) || ischar (match)))
    print_usage ();
  endif

  if (isempty (str) || isempty (match))
    finalstring = str;
  else
    if (ischar (str) && ! isvector (str))
      error("erase: STR must be a cell array of strings or a char vector");
    endif

    if (ischar (match) && ! isvector (match))
      error("erase: MATCH must be a cell array of strings or a char vector");
    endif

    if (ischar (match) && isvector (match))
      match = num2cell (match, 2);
    endif

    match = match(:);
    str_was_char = false;

    if (ischar (str))
      str = num2cell (str, 2);
      str_was_char = true;
    else
      str = cellstr (str);
    endif
    s = size (str);
    str = str(:);

    for i = 1:rows (str)
      ## Marked array to keep track of the deletions
      mask = zeros (1, numel (str{i}));
      for j = 1:rows (match)

          ind = strfind (str{i}, match{j}, "overlaps", false);
          if (isempty (ind))
            continue;
          endif

          tmp = zeros (size (mask));
          r = 0:(numel (match{j}) -1);
          q =ind'+r;
          tmp(ind'+r) = 1;

          ## Check if they overlap
          if (! any (tmp & mask))
            mask |= tmp;
          endif

      endfor

      str{i} = char (str{i})(! mask);

      if (numel (char (str{i})) == 0)
        str{i} = "";
      endif

    endfor

    str = reshape (str, s);

    finalstring = str;

    if (str_was_char)
      finalstring = char (finalstring);

    endif

  endif

endfunction



%!assert (erase ("Hello World!", " World"), "Hello!")
%!assert (erase ({"Hello World!"}, " World"), {"Hello!"})
%!error  <erase: STR must be a cell array of strings or a char vector> erase (char ("Hello", "World!"), "World"), char ("Hello ", "!")
%!assert (erase ({"Hello", "World!"}, "World"), {"Hello", "!"})
%%!assert (erase ("Hello World!", {"o"; "World"; " "}), "Hell!")

## Test overlaps
## from https://savannah.gnu.org/bugs/?52647#comment5
%!assert (erase ('ababa', 'aba'), 'ba');
%!assert (erase ('abababa', 'aba'), 'b');
%!assert (erase ('ababababa', 'aba'), 'bba')
%!assert (erase ('ababababa', {'aba', 'bba'}), 'bba');
%!assert (erase ('ababababa', {'aba'; 'bba'}), 'bba');
%!assert (erase ('ababababa ',{'aba', 'bba'}), 'bba ');
%!assert (erase ({' ababababa '}, {'aba', 'bba'}), {' bba '});
%!assert (erase ({' ababababa '}, {'aba'; 'bba'}), {' bba '});
%!assert (erase (' ababa ', {'aba', 'baba'}), ' ba ');
%!assert (erase (' Hello World t ',{'t';'llo'}),' He World  ')
%!assert (erase ({' Hello World t '},[ 'o ']),{' HellWorld t '})
%!assert (erase ('Hello World t ',{'ld '; 'o '}),'HellWort ')
%!assert (erase ('aba', 'aba'), char({''}));
%!assert (erase ({'aba'}, 'aba'), ({""}));
%!assert (erase ('', 'aba'), '');
%!assert (erase ({'abbabbabba'},{'abba'}),{'bb'});
%!assert (erase ({'ababababa';'abbabbabba'},'aba'),{'bba';'abbabbabba'})
%!assert (erase ({''},{''}),{''})
%!assert (erase ({'pppppppp'},'p'),{''})
%!assert (erase ('Hello World t ',{'ld '; 'o '}),'HellWort ')
%!error  <erase: MATCH must be a cell array of strings or a char vector> erase ('Hello World t ',['ld '; 'o '])
%!xtest  assert (erase ('Hello World t ',['ld '; 'o ']),'HellWort ')
%!assert (erase ({'Hello World t '},{'ld '; 'o '}),{'HellWort '})
%!assert (erase ('xfooybar', {'foo', 'bar'}), 'xy')
%!assert (erase ('xfoobary', {'foob', 'obar'}), 'xary')
%!assert (erase ('foogfoog',{'foo','g'}),'')
%!assert (erase ({'foobar','barfoo'},{'foo','bar'}),{'',''})
%!assert (erase ('        ',' '),'')


## Test input validation
%!error erase ()
%!error erase ("a")
%!error erase ("a", "b", "c")