aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fpm/src/fpm_strings.f90208
1 files changed, 118 insertions, 90 deletions
diff --git a/fpm/src/fpm_strings.f90 b/fpm/src/fpm_strings.f90
index 7623e43..8acd143 100644
--- a/fpm/src/fpm_strings.f90
+++ b/fpm/src/fpm_strings.f90
@@ -1,3 +1,33 @@
+!>## general routines for performing __string operations__
+!!
+!!### Types
+!! - **TYPE(STRING_T)** define a type to contain strings of variable length
+!!### Type Conversions
+!! - [[F_STRING]] return Fortran **CHARACTER** variable when given a C-like array of
+!! single characters terminated with a C_NULL_CHAR **CHARACTER**
+!! - [[STR]] Converts **INTEGER** or** LOGICAL** to **CHARACTER** string
+!!### Case
+!! - [[LOWER]] Changes a string to lowercase over optional specified column range
+!!### Parsing and joining
+!! - [[SPLIT]] parse string on delimiter characters and store tokens into an allocatable array
+!! - [[STRING_CAT]] Concatenate an array of **type(string_t)** into a single **CHARACTER** variable
+!! - [[JOIN]] append an array of **CHARACTER** variables into a single **CHARACTER** variable
+!!### Testing
+!! - [[STR_ENDS_WITH]] test if a **CHARACTER** string or array ends with a specified suffix
+!! - [[STRING_ARRAY_CONTAINS]] Check if array of **TYPE(STRING_T)** matches a particular **CHARACTER** string
+!! - **OPERATOR(.IN.)** Check if array of **TYPE(STRING_T)** matches a particular **CHARACTER** string
+!! - [[GLOB]] function compares text strings, one of which can have wildcards ('*' or '?').
+!!### Miscellaneous
+!! - [[LEN_TRIM]] Determine total trimmed length of **string_t** array
+!! - [[FNV_1A]] Hash a **CHARACTER**(*) string of default kind or a **TYPE(STRING_T)** array
+!! - [[REPLACE]] Returns string with characters in charset replaced with target_char.
+!! - [[RESIZE]] increase the size of a **TYPE(STRING_T)** array by N elements
+!! adding separators and suffix and prefix strings
+!!
+!!@note `If compiled with **OpenMP**, targets will be build in parallel where possible`.
+!!
+!src/fpm_model.f90: The process (see `[[build_model(subroutine)]]`)
+
module fpm_strings
use iso_fortran_env, only: int64
implicit none
@@ -39,6 +69,7 @@ end interface
contains
+!> test if a CHARACTER string ends with a specified suffix
pure logical function str_ends_with_str(s, e) result(r)
character(*), intent(in) :: s, e
integer :: n1, n2
@@ -51,6 +82,7 @@ pure logical function str_ends_with_str(s, e) result(r)
end if
end function str_ends_with_str
+!> test if a CHARACTER string ends with any of an array of suffixs
pure logical function str_ends_with_any(s, e) result(r)
character(*), intent(in) :: s
character(*), intent(in) :: e(:)
@@ -67,6 +99,8 @@ pure logical function str_ends_with_any(s, e) result(r)
end function str_ends_with_any
+!> return Fortran character variable when given a C-like array of
+!! single characters terminated with a C_NULL_CHAR character
function f_string(c_string)
use iso_c_binding
character(len=1), intent(in) :: c_string(:)
@@ -128,10 +162,10 @@ pure function fnv_1a_string_t(input, seed) result(hash)
end function fnv_1a_string_t
+ !>Author: John S. Urban
+ !!License: Public Domain
+ !! Changes a string to lowercase over optional specified column range
elemental pure function lower(str,begin,end) result (string)
- ! Changes a string to lowercase over specified range
- ! Author: John S. Urban
- ! License: Public Domain
character(*), intent(In) :: str
character(len(str)) :: string
@@ -161,9 +195,9 @@ elemental pure function lower(str,begin,end) result (string)
end function lower
+!> Check if array of TYPE(STRING_T) matches a particular CHARACTER string
+!!
logical function string_array_contains(search_string,array)
- ! Check if array of string_t contains a particular string
- !
character(*), intent(in) :: search_string
type(string_t), intent(in) :: array(:)
@@ -175,7 +209,7 @@ logical function string_array_contains(search_string,array)
end function string_array_contains
!> Concatenate an array of type(string_t) into
-!> a single character
+!> a single CHARACTER variable
function string_cat(strings,delim) result(cat)
type(string_t), intent(in) :: strings(:)
character(*), intent(in), optional :: delim
@@ -216,20 +250,19 @@ pure function string_len_trim(strings) result(n)
end function string_len_trim
+!>Author: John S. Urban
+!!License: Public Domain
+!! parse string on delimiter characters and store tokens into an allocatable array
subroutine split(input_line,array,delimiters,order,nulls)
- ! parse string on delimiter characters and store tokens into an allocatable array"
- ! Author: John S. Urban
- ! License: Public Domain
-
-
- ! given a line of structure " par1 par2 par3 ... parn " store each par(n) into a separate variable in array.
- ! o by default adjacent delimiters in the input string do not create an empty string in the output array
- ! o no quoting of delimiters is supported
- character(len=*),intent(in) :: input_line ! input string to tokenize
- character(len=*),optional,intent(in) :: delimiters ! list of delimiter characters
- character(len=*),optional,intent(in) :: order ! order of output array sequential|[reverse|right]
- character(len=*),optional,intent(in) :: nulls ! return strings composed of delimiters or not ignore|return|ignoreend
- character(len=:),allocatable,intent(out) :: array(:) ! output array of tokens
+ !! given a line of structure " par1 par2 par3 ... parn " store each par(n) into a separate variable in array.
+ !!
+ !! * by default adjacent delimiters in the input string do not create an empty string in the output array
+ !! * no quoting of delimiters is supported
+ character(len=*),intent(in) :: input_line !! input string to tokenize
+ character(len=*),optional,intent(in) :: delimiters !! list of delimiter characters
+ character(len=*),optional,intent(in) :: order !! order of output array sequential|[reverse|right]
+ character(len=*),optional,intent(in) :: nulls !! return strings composed of delimiters or not ignore|return|ignoreend
+ character(len=:),allocatable,intent(out) :: array(:) !! output array of tokens
integer :: n ! max number of strings INPUT_LINE could split into if all delimiter
integer,allocatable :: ibegin(:) ! positions in input string where tokens start
@@ -334,8 +367,8 @@ subroutine split(input_line,array,delimiters,order,nulls)
enddo
end subroutine split
+!> Returns string with characters in charset replaced with target_char.
pure function replace(string, charset, target_char) result(res)
- ! Returns string with characters in charset replaced with target_char.
character(*), intent(in) :: string
character, intent(in) :: charset(:), target_char
character(len(string)) :: res
@@ -348,6 +381,7 @@ pure function replace(string, charset, target_char) result(res)
end do
end function replace
+!> increase the size of a TYPE(STRING_T) array by N elements
subroutine resize_string(list, n)
!> Instance of the array to be resized
type(string_t), allocatable, intent(inout) :: list(:)
@@ -383,14 +417,14 @@ subroutine resize_string(list, n)
end subroutine resize_string
-pure function join(str,sep,trm,left,right,start,end) result (string)
-!>
-!!##NAME
+!>AUTHOR: John S. Urban
+!!LICENSE: Public Domain
+!!## NAME
!! join(3f) - [fpm_strings:EDITING] append CHARACTER variable array into
!! a single CHARACTER variable with specified separator
!! (LICENSE:PD)
!!
-!!##SYNOPSIS
+!!## SYNOPSIS
!!
!! pure function join(str,sep,trm,left,right,start,end) result (string)
!!
@@ -403,13 +437,13 @@ pure function join(str,sep,trm,left,right,start,end) result (string)
!! character(len=*),intent(in),optional :: end
!! character(len=:),allocatable :: string
!!
-!!##DESCRIPTION
-!! JOIN(3f) appends the elements of a CHARACTER array into a single
-!! CHARACTER variable, with elements 1 to N joined from left to right.
-!! By default each element is trimmed of trailing spaces and the
-!! default separator is a null string.
+!!## DESCRIPTION
+!! JOIN(3f) appends the elements of a CHARACTER array into a single
+!! CHARACTER variable, with elements 1 to N joined from left to right.
+!! By default each element is trimmed of trailing spaces and the
+!! default separator is a null string.
!!
-!!##OPTIONS
+!!## OPTIONS
!! STR(:) array of CHARACTER variables to be joined
!! SEP separator string to place between each variable. defaults
!! to a null string.
@@ -420,50 +454,47 @@ pure function join(str,sep,trm,left,right,start,end) result (string)
!! TRM option to trim each element of STR of trailing
!! spaces. Defaults to .TRUE.
!!
-!!##RESULT
+!!## RESULT
!! STRING CHARACTER variable composed of all of the elements of STR()
!! appended together with the optional separator SEP placed
!! between the elements.
!!
-!!##EXAMPLE
+!!## EXAMPLE
!!
!! Sample program:
-!!
-!! program demo_join
-!! use fpm_strings, only: join
-!! implicit none
-!! character(len=:),allocatable :: s(:)
-!! character(len=:),allocatable :: out
-!! integer :: i
-!! s=[character(len=10) :: 'United',' we',' stand,', &
-!! & ' divided',' we fall.']
-!! out=join(s)
-!! write(*,'(a)') out
-!! write(*,'(a)') join(s,trm=.false.)
-!! write(*,'(a)') (join(s,trm=.false.,sep='|'),i=1,3)
-!! write(*,'(a)') join(s,sep='<>')
-!! write(*,'(a)') join(s,sep=';',left='[',right=']')
-!! write(*,'(a)') join(s,left='[',right=']')
-!! write(*,'(a)') join(s,left='>>')
-!! end program demo_join
+!!```fortran
+!! program demo_join
+!! use fpm_strings, only: join
+!! implicit none
+!! character(len=:),allocatable :: s(:)
+!! character(len=:),allocatable :: out
+!! integer :: i
+!! s=[character(len=10) :: 'United',' we',' stand,', &
+!! & ' divided',' we fall.']
+!! out=join(s)
+!! write(*,'(a)') out
+!! write(*,'(a)') join(s,trm=.false.)
+!! write(*,'(a)') (join(s,trm=.false.,sep='|'),i=1,3)
+!! write(*,'(a)') join(s,sep='<>')
+!! write(*,'(a)') join(s,sep=';',left='[',right=']')
+!! write(*,'(a)') join(s,left='[',right=']')
+!! write(*,'(a)') join(s,left='>>')
+!! end program demo_join
+!!```fortran
!!
!! Expected output:
!!
-!! United we stand, divided we fall.
-!! United we stand, divided we fall.
-!! United | we | stand, | divided | we fall.
-!! United | we | stand, | divided | we fall.
-!! United | we | stand, | divided | we fall.
-!! United<> we<> stand,<> divided<> we fall.
-!! [United];[ we];[ stand,];[ divided];[ we fall.]
-!! [United][ we][ stand,][ divided][ we fall.]
-!! >>United>> we>> stand,>> divided>> we fall.
-!!
-!!##AUTHOR
-!! John S. Urban
+!! United we stand, divided we fall.
+!! United we stand, divided we fall.
+!! United | we | stand, | divided | we fall.
+!! United | we | stand, | divided | we fall.
+!! United | we | stand, | divided | we fall.
+!! United<> we<> stand,<> divided<> we fall.
+!! [United];[ we];[ stand,];[ divided];[ we fall.]
+!! [United][ we][ stand,][ divided][ we fall.]
+!! >>United>> we>> stand,>> divided>> we fall.
!!
-!!##LICENSE
-!! Public Domain
+pure function join(str,sep,trm,left,right,start,end) result (string)
! @(#)join(3f): append an array of character variables with specified separator into a single CHARACTER variable
@@ -503,29 +534,29 @@ character(len=:),allocatable :: right_local
if(present(end))string=string//end
end function join
-function glob(tame,wild)
-!>
-!!##NAME
+!>##AUTHOR John S. Urban
+!!##LICENSE Public Domain
+!!## NAME
!! glob(3f) - [fpm_strings:COMPARE] compare given string for match to
!! pattern which may contain wildcard characters
!! (LICENSE:PD)
!!
-!!##SYNOPSIS
+!!## SYNOPSIS
!!
!! logical function glob(string, pattern )
!!
!! character(len=*),intent(in) :: string
!! character(len=*),intent(in) :: pattern
!!
-!!##DESCRIPTION
-!! glob(3f) compares given STRING for match to PATTERN which may
-!! contain wildcard characters.
+!!## DESCRIPTION
+!! glob(3f) compares given STRING for match to PATTERN which may
+!! contain wildcard characters.
!!
-!! In this version to get a match the entire string must be described
-!! by PATTERN. Trailing whitespace is significant, so trim the input
-!! string to have trailing whitespace ignored.
+!! In this version to get a match the entire string must be described
+!! by PATTERN. Trailing whitespace is significant, so trim the input
+!! string to have trailing whitespace ignored.
!!
-!!##OPTIONS
+!!## OPTIONS
!! string the input string to test to see if it contains the pattern.
!! pattern the following simple globbing options are available
!!
@@ -537,7 +568,7 @@ function glob(tame,wild)
!! o There is no escape character, so matching strings with
!! literal question mark and asterisk is problematic.
!!
-!!##EXAMPLES
+!!## EXAMPLES
!!
!! Example program
!!
@@ -729,21 +760,18 @@ function glob(tame,wild)
!!
!! Expected output
!!
-!!##AUTHOR
-!! John S. Urban
!!
-!!##REFERENCE
+!!## REFERENCE
!! The article "Matching Wildcards: An Empirical Way to Tame an Algorithm"
!! in Dr Dobb's Journal, By Kirk J. Krauss, October 07, 2014
!!
-!!##LICENSE
-!! Public Domain
+function glob(tame,wild)
! @(#)fpm_strings::glob(3f): function compares text strings, one of which can have wildcards ('*' or '?').
-logical :: glob
-character(len=*) :: tame ! A string without wildcards
-character(len=*) :: wild ! A (potentially) corresponding string with wildcards
+logical :: glob !! result of test
+character(len=*) :: tame !! A string without wildcards to compare to the globbing expression
+character(len=*) :: wild !! A (potentially) corresponding string with wildcards
character(len=len(tame)+1) :: tametext
character(len=len(wild)+1) :: wildtext
character(len=1),parameter :: NULL=char(0)
@@ -829,8 +857,8 @@ character(len=:),allocatable :: tbookmark, wbookmark
enddo
end function glob
+!> Returns the length of the string representation of 'i'
pure integer function str_int_len(i) result(sz)
-! Returns the length of the string representation of 'i'
integer, intent(in) :: i
integer, parameter :: MAX_STR = 100
character(MAX_STR) :: s
@@ -840,15 +868,15 @@ write(s, '(i0)') i
sz = len_trim(s)
end function
+!> Converts integer "i" to string
pure function str_int(i) result(s)
-! Converts integer "i" to string
integer, intent(in) :: i
character(len=str_int_len(i)) :: s
write(s, '(i0)') i
end function
+!> Returns the length of the string representation of 'i'
pure integer function str_int64_len(i) result(sz)
-! Returns the length of the string representation of 'i'
integer(int64), intent(in) :: i
integer, parameter :: MAX_STR = 100
character(MAX_STR) :: s
@@ -858,15 +886,15 @@ write(s, '(i0)') i
sz = len_trim(s)
end function
+!> Converts integer "i" to string
pure function str_int64(i) result(s)
-! Converts integer "i" to string
integer(int64), intent(in) :: i
character(len=str_int64_len(i)) :: s
write(s, '(i0)') i
end function
+!> Returns the length of the string representation of 'l'
pure integer function str_logical_len(l) result(sz)
-! Returns the length of the string representation of 'l'
logical, intent(in) :: l
if (l) then
sz = 6
@@ -875,8 +903,8 @@ else
end if
end function
+!> Converts logical "l" to string
pure function str_logical(l) result(s)
-! Converts logical "l" to string
logical, intent(in) :: l
character(len=str_logical_len(l)) :: s
if (l) then