Skip to content
Snippets Groups Projects

util_string: dynamically allocate and expand string lists

Merged Roland Wirth requested to merge rwirth/dynamic-string-lists into master
Files
2
+ 53
7
@@ -77,6 +77,8 @@ MODULE mo_util_string
MODULE PROCEDURE charArray_equal_char
END INTERFACE charArray_equal
PUBLIC :: new_list
INTERFACE add_to_list
MODULE PROCEDURE add_to_list, add_to_list_1
END INTERFACE add_to_list
@@ -575,6 +577,20 @@ CONTAINS
END DO
END SUBROUTINE difference
!==============================================================================
!> Create a new empty string list
!!
!! Allocates space for 8 strings initially. Size doubles every time the list
!! has to be expanded, so adding to the list is constant amortized time.
SUBROUTINE new_list(str_list, nitems)
CHARACTER(len=*), ALLOCATABLE, INTENT(OUT) :: str_list(:)
INTEGER, INTENT(OUT) :: nitems
ALLOCATE (str_list(8))
nitems = 0
END SUBROUTINE new_list
!==============================================================================
!+ Add entries from list 2 to list 1, if they are not already present
!+ in list 1.
@@ -582,20 +598,38 @@ CONTAINS
! This is a very crude implementation, quadratic complexity.
!
SUBROUTINE add_to_list(str_list1, nitems1, str_list2, nitems2)
CHARACTER(len=*), INTENT(INOUT) :: str_list1(:)
CHARACTER(len=*), ALLOCATABLE, INTENT(INOUT) :: str_list1(:)
INTEGER, INTENT(INOUT) :: nitems1
CHARACTER(len=*), INTENT(IN) :: str_list2(:)
INTEGER, INTENT(IN) :: nitems2
CHARACTER(len=*), INTENT(IN) :: str_list2(:)
INTEGER, OPTIONAL, INTENT(IN) :: nitems2
! local variables
INTEGER :: iread, i
INTEGER :: iread, i, nitems2_
CHARACTER(len=LEN(str_list1)), ALLOCATABLE :: tmp(:)
IF (.NOT. ALLOCATED(str_list1)) THEN
CALL new_list(str_list1, nitems1)
END IF
IF (PRESENT(nitems2)) THEN
nitems2_ = nitems2
ELSE
nitems2_ = SIZE(str_list2)
END IF
! Loop over all items that should potentially be added
item_add_loop: DO iread = 1, nitems2
item_add_loop: DO iread = 1, nitems2_
! Loop over all items in the target list (list 1) to
! check if item is already in string list 1:
DO i = 1, nitems1
IF (str_list1(i) == str_list2(iread)) CYCLE item_add_loop
END DO
IF (nitems1 >= SIZE(str_list1)) THEN
ALLOCATE (tmp(2*SIZE(str_list1)))
tmp(1:nitems1) = str_list1(1:nitems1)
CALL MOVE_ALLOC(tmp, str_list1)
END IF
nitems1 = nitems1 + 1
str_list1(nitems1) = str_list2(iread)
END DO item_add_loop
@@ -603,17 +637,29 @@ CONTAINS
END SUBROUTINE add_to_list
SUBROUTINE add_to_list_1(str_list, nitems, str)
CHARACTER(len=*), INTENT(INOUT) :: str_list(:)
CHARACTER(len=*), ALLOCATABLE, INTENT(INOUT) :: str_list(:)
INTEGER, INTENT(INOUT) :: nitems
CHARACTER(len=*), INTENT(IN) :: str
! local variables
INTEGER :: iread, i
INTEGER :: i
CHARACTER(len=LEN(str_list)), ALLOCATABLE :: tmp(:)
IF (.NOT. ALLOCATED(str_list)) THEN
CALL new_list(str_list, nitems)
END IF
! Loop over all items in the target list to
! check if item is already in that list
DO i = 1, nitems
IF (str_list(i) == str) RETURN
END DO
IF (nitems >= SIZE(str_list)) THEN
ALLOCATE (tmp(2*SIZE(str_list)))
tmp(1:nitems) = str_list(1:nitems)
CALL MOVE_ALLOC(tmp, str_list)
END IF
nitems = nitems + 1
str_list(nitems) = str
Loading