Skip to content

Commit 92b6e50

Browse files
committed
add split_first_last
1 parent c0b8643 commit 92b6e50

File tree

1 file changed

+70
-1
lines changed

1 file changed

+70
-1
lines changed

src/fpm_strings.f90

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
!! - [[LOWER]] Changes a string to lowercase over optional specified column range
1414
!!### Parsing and joining
1515
!! - [[SPLIT]] parse string on delimiter characters and store tokens into an allocatable array
16+
!! - [[SPLIT_FIRST_LAST]] Computes the first and last indices of tokens in input string, delimited by the characters in set,
17+
!! and stores them into first and last output arrays.
1618
!! - [[STRING_CAT]] Concatenate an array of **type(string_t)** into a single **CHARACTER** variable
1719
!! - [[JOIN]] append an array of **CHARACTER** variables into a single **CHARACTER** variable
1820
!!### Testing
@@ -40,7 +42,7 @@ module fpm_strings
4042
implicit none
4143

4244
private
43-
public :: f_string, lower, split, str_ends_with, string_t, str_begins_with_str
45+
public :: f_string, lower, split, split_first_last, str_ends_with, string_t, str_begins_with_str
4446
public :: to_fortran_name, is_fortran_name
4547
public :: string_array_contains, string_cat, len_trim, operator(.in.), fnv_1a
4648
public :: replace, resize, str, join, glob
@@ -463,6 +465,73 @@ subroutine split(input_line,array,delimiters,order,nulls)
463465
enddo
464466
end subroutine split
465467

468+
!! Author: Milan Curcic
469+
!! Computes the first and last indices of tokens in input string, delimited
470+
!! by the characters in set, and stores them into first and last output
471+
!! arrays.
472+
pure subroutine split_first_last(string, set, first, last)
473+
character(*), intent(in) :: string
474+
character(*), intent(in) :: set
475+
integer, allocatable, intent(out) :: first(:)
476+
integer, allocatable, intent(out) :: last(:)
477+
478+
integer, dimension(len(string) + 1) :: istart, iend
479+
integer :: p, n, slen
480+
481+
slen = len(string)
482+
483+
n = 0
484+
if (slen > 0) then
485+
p = 0
486+
do while (p < slen)
487+
n = n + 1
488+
istart(n) = min(p + 1, slen)
489+
call split_pos(string, set, p)
490+
iend(n) = p - 1
491+
end do
492+
end if
493+
494+
first = istart(:n)
495+
last = iend(:n)
496+
497+
end subroutine split_first_last
498+
499+
!! Author: Milan Curcic
500+
!! If back is absent, computes the leftmost token delimiter in string whose
501+
!! position is > pos. If back is present and true, computes the rightmost
502+
!! token delimiter in string whose position is < pos. The result is stored
503+
!! in pos.
504+
pure subroutine split_pos(string, set, pos, back)
505+
character(*), intent(in) :: string
506+
character(*), intent(in) :: set
507+
integer, intent(in out) :: pos
508+
logical, intent(in), optional :: back
509+
510+
logical :: backward
511+
integer :: result_pos, bound
512+
513+
if (len(string) == 0) then
514+
pos = 1
515+
return
516+
end if
517+
518+
!TODO use optval when implemented in stdlib
519+
!backward = optval(back, .false.)
520+
backward = .false.
521+
if (present(back)) backward = back
522+
523+
if (backward) then
524+
bound = min(len(string), max(pos - 1, 0))
525+
result_pos = scan(string(:bound), set, back=.true.)
526+
else
527+
result_pos = scan(string(min(pos + 1, len(string)):), set) + pos
528+
if (result_pos < pos + 1) result_pos = len(string) + 1
529+
end if
530+
531+
pos = result_pos
532+
533+
end subroutine split_pos
534+
466535
!> Returns string with characters in charset replaced with target_char.
467536
pure function replace(string, charset, target_char) result(res)
468537
character(*), intent(in) :: string

0 commit comments

Comments
 (0)