Skip to content

Commit 4ed69eb

Browse files
authored
Merge pull request #436 from Aman-Godara/replace_all
implemented low-level replace_all function
2 parents 9fb85ff + 7d38373 commit 4ed69eb

File tree

3 files changed

+320
-56
lines changed

3 files changed

+320
-56
lines changed

doc/specs/stdlib_strings.md

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,6 @@ Default value of `occurrence` is set to `1`.
283283
If `consider_overlapping` is not provided or is set to `.true.` the function counts two overlapping occurrences of substring as two different occurrences.
284284
If `occurrence`th occurrence is not found, function returns `0`.
285285

286-
287286
#### Syntax
288287

289288
`string = [[stdlib_strings(module):find(interface)]] (string, pattern [, occurrence, consider_overlapping])`
@@ -318,7 +317,7 @@ program demo_find
318317
use stdlib_string_type, only: string_type, assignment(=)
319318
use stdlib_strings, only : find
320319
implicit none
321-
string_type :: string
320+
type(string_type) :: string
322321
323322
string = "needle in the character-stack"
324323
@@ -328,3 +327,58 @@ program demo_find
328327
329328
end program demo_find
330329
```
330+
331+
332+
<!-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -->
333+
### `replace_all`
334+
335+
#### Description
336+
337+
Replaces all occurrences of substring `pattern` in the input `string` with the replacement `replacement`.
338+
Occurrences overlapping on a base occurrence will not be replaced.
339+
340+
#### Syntax
341+
342+
`string = [[stdlib_strings(module):replace_all(interface)]] (string, pattern, replacement)`
343+
344+
#### Status
345+
346+
Experimental
347+
348+
#### Class
349+
350+
Pure function
351+
352+
#### Argument
353+
354+
- `string`: Character scalar or [[stdlib_string_type(module):string_type(type)]].
355+
This argument is intent(in).
356+
- `pattern`: Character scalar or [[stdlib_string_type(module):string_type(type)]].
357+
This argument is intent(in).
358+
- `replacement`: Character scalar or [[stdlib_string_type(module):string_type(type)]].
359+
This argument is intent(in).
360+
361+
#### Result value
362+
363+
The result is of the same type as `string`.
364+
365+
#### Example
366+
367+
```fortran
368+
program demo_replace_all
369+
use stdlib_string_type, only: string_type, assignment(=)
370+
use stdlib_strings, only : replace_all
371+
implicit none
372+
type(string_type) :: string
373+
374+
string = "hurdles here, hurdles there, hurdles everywhere"
375+
! string <-- "hurdles here, hurdles there, hurdles everywhere"
376+
377+
print'(a)', replace_all(string, "hurdles", "learn from")
378+
! "learn from here, learn from there, learn from everywhere"
379+
380+
string = replace_all(string, "hurdles", "technology")
381+
! string <-- "technology here, technology there, technology everywhere"
382+
383+
end program demo_replace_all
384+
```

src/stdlib_strings.f90

Lines changed: 151 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module stdlib_strings
1212

1313
public :: strip, chomp
1414
public :: starts_with, ends_with
15-
public :: slice, find
15+
public :: slice, find, replace_all
1616

1717

1818
!> Remove leading and trailing whitespace characters.
@@ -79,6 +79,20 @@ module stdlib_strings
7979
module procedure :: find_char_char
8080
end interface find
8181

82+
!> Replaces all the occurrences of substring 'pattern' in the input 'string'
83+
!> with the replacement 'replacement'
84+
!> Version: experimental
85+
interface replace_all
86+
module procedure :: replace_all_string_string_string
87+
module procedure :: replace_all_string_string_char
88+
module procedure :: replace_all_string_char_string
89+
module procedure :: replace_all_char_string_string
90+
module procedure :: replace_all_string_char_char
91+
module procedure :: replace_all_char_string_char
92+
module procedure :: replace_all_char_char_string
93+
module procedure :: replace_all_char_char_char
94+
end interface replace_all
95+
8296
contains
8397

8498

@@ -353,7 +367,7 @@ pure function slice_char(string, first, last, stride) result(sliced_string)
353367
end if
354368

355369
if (present(first)) then
356-
first_index = first
370+
first_index = first
357371
end if
358372
if (present(last)) then
359373
last_index = last
@@ -499,5 +513,140 @@ pure function compute_lps(string) result(lps_array)
499513

500514
end function compute_lps
501515

516+
!> Replaces all occurrences of substring 'pattern' in the input 'string'
517+
!> with the replacement 'replacement'
518+
!> Returns a new string
519+
pure function replace_all_string_string_string(string, pattern, replacement) result(res)
520+
type(string_type), intent(in) :: string
521+
type(string_type), intent(in) :: pattern
522+
type(string_type), intent(in) :: replacement
523+
type(string_type) :: res
524+
525+
res = string_type(replace_all(char(string), &
526+
& char(pattern), char(replacement)))
527+
528+
end function replace_all_string_string_string
529+
530+
!> Replaces all occurrences of substring 'pattern' in the input 'string'
531+
!> with the replacement 'replacement'
532+
!> Returns a new string
533+
pure function replace_all_string_string_char(string, pattern, replacement) result(res)
534+
type(string_type), intent(in) :: string
535+
type(string_type), intent(in) :: pattern
536+
character(len=*), intent(in) :: replacement
537+
type(string_type) :: res
538+
539+
res = string_type(replace_all(char(string), char(pattern), replacement))
540+
541+
end function replace_all_string_string_char
542+
543+
!> Replaces all occurrences of substring 'pattern' in the input 'string'
544+
!> with the replacement 'replacement'
545+
!> Returns a new string
546+
pure function replace_all_string_char_string(string, pattern, replacement) result(res)
547+
type(string_type), intent(in) :: string
548+
character(len=*), intent(in) :: pattern
549+
type(string_type), intent(in) :: replacement
550+
type(string_type) :: res
551+
552+
res = string_type(replace_all(char(string), pattern, char(replacement)))
553+
554+
end function replace_all_string_char_string
555+
556+
!> Replaces all occurrences of substring 'pattern' in the input 'string'
557+
!> with the replacement 'replacement'
558+
!> Returns a new string
559+
pure function replace_all_char_string_string(string, pattern, replacement) result(res)
560+
character(len=*), intent(in) :: string
561+
type(string_type), intent(in) :: pattern
562+
type(string_type), intent(in) :: replacement
563+
character(len=:), allocatable :: res
564+
565+
res = replace_all(string, char(pattern), char(replacement))
566+
567+
end function replace_all_char_string_string
568+
569+
!> Replaces all occurrences of substring 'pattern' in the input 'string'
570+
!> with the replacement 'replacement'
571+
!> Returns a new string
572+
pure function replace_all_string_char_char(string, pattern, replacement) result(res)
573+
type(string_type), intent(in) :: string
574+
character(len=*), intent(in) :: pattern
575+
character(len=*), intent(in) :: replacement
576+
type(string_type) :: res
577+
578+
res = string_type(replace_all(char(string), pattern, replacement))
579+
580+
end function replace_all_string_char_char
581+
582+
!> Replaces all occurrences of substring 'pattern' in the input 'string'
583+
!> with the replacement 'replacement'
584+
!> Returns a new string
585+
pure function replace_all_char_string_char(string, pattern, replacement) result(res)
586+
character(len=*), intent(in) :: string
587+
type(string_type), intent(in) :: pattern
588+
character(len=*), intent(in) :: replacement
589+
character(len=:), allocatable :: res
590+
591+
res = replace_all(string, char(pattern), replacement)
592+
593+
end function replace_all_char_string_char
594+
595+
!> Replaces all occurrences of substring 'pattern' in the input 'string'
596+
!> with the replacement 'replacement'
597+
!> Returns a new string
598+
pure function replace_all_char_char_string(string, pattern, replacement) result(res)
599+
character(len=*), intent(in) :: string
600+
character(len=*), intent(in) :: pattern
601+
type(string_type), intent(in) :: replacement
602+
character(len=:), allocatable :: res
603+
604+
res = replace_all(string, pattern, char(replacement))
605+
606+
end function replace_all_char_char_string
607+
608+
!> Replaces all the occurrences of substring 'pattern' in the input 'string'
609+
!> with the replacement 'replacement'
610+
!> Returns a new string
611+
pure function replace_all_char_char_char(string, pattern, replacement) result(res)
612+
character(len=*), intent(in) :: string
613+
character(len=*), intent(in) :: pattern
614+
character(len=*), intent(in) :: replacement
615+
character(len=:), allocatable :: res
616+
integer :: lps_array(len(pattern))
617+
integer :: s_i, p_i, last, length_string, length_pattern
618+
619+
res = ""
620+
length_string = len(string)
621+
length_pattern = len(pattern)
622+
last = 1
623+
624+
if (length_pattern > 0 .and. length_pattern <= length_string) then
625+
lps_array = compute_lps(pattern)
626+
627+
s_i = 1
628+
p_i = 1
629+
do while (s_i <= length_string)
630+
if (string(s_i:s_i) == pattern(p_i:p_i)) then
631+
if (p_i == length_pattern) then
632+
res = res // &
633+
& string(last : s_i - length_pattern) // &
634+
& replacement
635+
last = s_i + 1
636+
p_i = 0
637+
end if
638+
s_i = s_i + 1
639+
p_i = p_i + 1
640+
else if (p_i > 1) then
641+
p_i = lps_array(p_i - 1) + 1
642+
else
643+
s_i = s_i + 1
644+
end if
645+
end do
646+
end if
647+
648+
res = res // string(last : length_string)
649+
650+
end function replace_all_char_char_char
502651

503652
end module stdlib_strings

0 commit comments

Comments
 (0)