Skip to content

implemented low-level replace_all function #436

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jul 4, 2021
Next Next commit
implemented replace_all function, added some test_cases for replace_all
  • Loading branch information
aman-godara committed Jun 20, 2021
commit e325c2bce896740ba290c8a0e5c74ada64b23609
66 changes: 65 additions & 1 deletion src/stdlib_strings.f90
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module stdlib_strings

public :: strip, chomp
public :: starts_with, ends_with
public :: slice, find
public :: slice, find, replace_all


!> Remove leading and trailing whitespace characters.
Expand Down Expand Up @@ -79,6 +79,20 @@ module stdlib_strings
module procedure :: find_char_char
end interface find

!> Replaces all the occurrences of substring 'pattern' in the input 'string'
!> with the replacement 'replacement'
!> Version: experimental
interface replace_all
!module procedure :: replace_all_string_string_string
!module procedure :: replace_all_string_string_char
!module procedure :: replace_all_string_char_string
!module procedure :: replace_all_char_string_string
!module procedure :: replace_all_string_char_char
!module procedure :: replace_all_char_string_char
!module procedure :: replace_all_char_char_string
module procedure :: replace_all_char_char_char
end interface replace_all

contains


Expand Down Expand Up @@ -499,5 +513,55 @@ pure function compute_lps(string) result(lps_array)

end function compute_lps

!> Replaces all the occurrences of substring 'pattern' in the input 'string'
!> with the replacement 'replacement'
!> Returns a new string
pure function replace_all_char_char_char(string, pattern, replacement, replace_overlapping) result(res)
character(len=*), intent(in) :: string
character(len=*), intent(in) :: pattern
character(len=*), intent(in) :: replacement
logical, intent(in), optional :: replace_overlapping
character(:), allocatable :: res
integer :: lps_array(len(pattern))
integer :: s_i, p_i, last, length_string, length_pattern
logical :: replace_overlapping_

res = ""
replace_overlapping_ = optval(replace_overlapping, .false.)
length_string = len(string)
length_pattern = len(pattern)
last = 1

if (length_pattern > 0 .and. length_pattern <= length_string) then
lps_array = compute_lps(pattern)

s_i = 1
p_i = 1
do while(s_i <= length_string)
if (string(s_i:s_i) == pattern(p_i:p_i)) then
if (p_i == length_pattern) then
res = res // &
& slice(string, first=last, last=s_i - length_pattern, stride=1) // &
& replacement
last = s_i + 1
if (replace_overlapping_) then
p_i = lps_array(p_i)
else
p_i = 0
end if
end if
s_i = s_i + 1
p_i = p_i + 1
else if (p_i > 1) then
p_i = lps_array(p_i - 1) + 1
else
s_i = s_i + 1
end if
end do
end if

res = res // slice(string, first=last)

end function replace_all_char_char_char

end module stdlib_strings
14 changes: 13 additions & 1 deletion src/tests/string/test_string_functions.f90
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module test_string_functions
use stdlib_error, only : check
use stdlib_string_type, only : string_type, assignment(=), operator(==), &
to_lower, to_upper, to_title, to_sentence, reverse
use stdlib_strings, only: slice, find
use stdlib_strings, only: slice, find, replace_all
use stdlib_optval, only: optval
use stdlib_ascii, only : to_string
implicit none
Expand Down Expand Up @@ -318,6 +318,17 @@ pure function carray_to_string(carray) result(string)
string = transfer(carray, string)
end function carray_to_string

subroutine test_replace_all
character(len=:), allocatable :: test_string
test_string = "qwqwqwqwqwqwqwqwpqr"
call check(replace_all(test_string, "qwq", "wqw", .true.) == "wqwwqwwqwwqwwqwwqwwqwwpqr")
call check(replace_all(test_string, "qwq", "abcd") == "abcdwabcdwabcdwabcdwpqr")
call check(replace_all(test_string, "", "abcd") == test_string)

call check(replace_all("", "qwq", "abcd") == "")

end subroutine test_replace_all

end module test_string_functions


Expand All @@ -333,5 +344,6 @@ program tester
call test_slice_string
call test_slice_gen
call test_find
call test_replace_all

end program tester