|
13 | 13 | !! - [[LOWER]] Changes a string to lowercase over optional specified column range
|
14 | 14 | !!### Parsing and joining
|
15 | 15 | !! - [[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. |
16 | 18 | !! - [[STRING_CAT]] Concatenate an array of **type(string_t)** into a single **CHARACTER** variable
|
17 | 19 | !! - [[JOIN]] append an array of **CHARACTER** variables into a single **CHARACTER** variable
|
18 | 20 | !!### Testing
|
@@ -40,7 +42,7 @@ module fpm_strings
|
40 | 42 | implicit none
|
41 | 43 |
|
42 | 44 | 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 |
44 | 46 | public :: to_fortran_name, is_fortran_name
|
45 | 47 | public :: string_array_contains, string_cat, len_trim, operator(.in.), fnv_1a
|
46 | 48 | public :: replace, resize, str, join, glob
|
@@ -463,6 +465,73 @@ subroutine split(input_line,array,delimiters,order,nulls)
|
463 | 465 | enddo
|
464 | 466 | end subroutine split
|
465 | 467 |
|
| 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 | + |
466 | 535 | !> Returns string with characters in charset replaced with target_char.
|
467 | 536 | pure function replace(string, charset, target_char) result(res)
|
468 | 537 | character(*), intent(in) :: string
|
|
0 commit comments