1
+ ! >## general routines for performing __string operations__
2
+ ! !
3
+ ! !### Types
4
+ ! ! - **TYPE(STRING_T)** define a type to contain strings of variable length
5
+ ! !### Type Conversions
6
+ ! ! - [[F_STRING]] return Fortran **CHARACTER** variable when given a C-like array of
7
+ ! ! single characters terminated with a C_NULL_CHAR **CHARACTER**
8
+ ! ! - [[STR]] Converts **INTEGER** or** LOGICAL** to **CHARACTER** string
9
+ ! !### Case
10
+ ! ! - [[LOWER]] Changes a string to lowercase over optional specified column range
11
+ ! !### Parsing and joining
12
+ ! ! - [[SPLIT]] parse string on delimiter characters and store tokens into an allocatable array
13
+ ! ! - [[STRING_CAT]] Concatenate an array of **type(string_t)** into a single **CHARACTER** variable
14
+ ! ! - [[JOIN]] append an array of **CHARACTER** variables into a single **CHARACTER** variable
15
+ ! !### Testing
16
+ ! ! - [[STR_ENDS_WITH]] test if a **CHARACTER** string or array ends with a specified suffix
17
+ ! ! - [[STRING_ARRAY_CONTAINS]] Check if array of **TYPE(STRING_T)** matches a particular **CHARACTER** string
18
+ ! ! - **OPERATOR(.IN.)** Check if array of **TYPE(STRING_T)** matches a particular **CHARACTER** string
19
+ ! ! - [[GLOB]] function compares text strings, one of which can have wildcards ('*' or '?').
20
+ ! !### Miscellaneous
21
+ ! ! - [[LEN_TRIM]] Determine total trimmed length of **string_t** array
22
+ ! ! - [[FNV_1A]] Hash a **CHARACTER**(*) string of default kind or a **TYPE(STRING_T)** array
23
+ ! ! - [[REPLACE]] Returns string with characters in charset replaced with target_char.
24
+ ! ! - [[RESIZE]] increase the size of a **TYPE(STRING_T)** array by N elements
25
+ ! ! adding separators and suffix and prefix strings
26
+ ! !
27
+ ! !@note `If compiled with **OpenMP**, targets will be build in parallel where possible`.
28
+ ! !
29
+ ! src/fpm_model.f90: The process (see `[[build_model(subroutine)]]`)
30
+
1
31
module fpm_strings
2
32
use iso_fortran_env, only: int64
3
33
implicit none
@@ -39,6 +69,7 @@ module fpm_strings
39
69
40
70
contains
41
71
72
+ ! > test if a CHARACTER string ends with a specified suffix
42
73
pure logical function str_ends_with_str(s, e) result(r)
43
74
character (* ), intent (in ) :: s, e
44
75
integer :: n1, n2
@@ -51,6 +82,7 @@ pure logical function str_ends_with_str(s, e) result(r)
51
82
end if
52
83
end function str_ends_with_str
53
84
85
+ ! > test if a CHARACTER string ends with any of an array of suffixs
54
86
pure logical function str_ends_with_any(s, e) result(r)
55
87
character (* ), intent (in ) :: s
56
88
character (* ), intent (in ) :: e(:)
@@ -67,6 +99,8 @@ pure logical function str_ends_with_any(s, e) result(r)
67
99
68
100
end function str_ends_with_any
69
101
102
+ ! > return Fortran character variable when given a C-like array of
103
+ ! ! single characters terminated with a C_NULL_CHAR character
70
104
function f_string (c_string )
71
105
use iso_c_binding
72
106
character (len= 1 ), intent (in ) :: c_string(:)
@@ -128,10 +162,10 @@ pure function fnv_1a_string_t(input, seed) result(hash)
128
162
end function fnv_1a_string_t
129
163
130
164
165
+ ! >Author: John S. Urban
166
+ ! !License: Public Domain
167
+ ! ! Changes a string to lowercase over optional specified column range
131
168
elemental pure function lower(str,begin,end) result (string)
132
- ! Changes a string to lowercase over specified range
133
- ! Author: John S. Urban
134
- ! License: Public Domain
135
169
136
170
character (* ), intent (In ) :: str
137
171
character (len (str)) :: string
@@ -161,9 +195,9 @@ elemental pure function lower(str,begin,end) result (string)
161
195
end function lower
162
196
163
197
198
+ ! > Check if array of TYPE(STRING_T) matches a particular CHARACTER string
199
+ ! !
164
200
logical function string_array_contains (search_string ,array )
165
- ! Check if array of string_t contains a particular string
166
- !
167
201
character (* ), intent (in ) :: search_string
168
202
type (string_t), intent (in ) :: array(:)
169
203
@@ -175,7 +209,7 @@ logical function string_array_contains(search_string,array)
175
209
end function string_array_contains
176
210
177
211
! > Concatenate an array of type(string_t) into
178
- ! > a single character
212
+ ! > a single CHARACTER variable
179
213
function string_cat (strings ,delim ) result(cat)
180
214
type (string_t), intent (in ) :: strings(:)
181
215
character (* ), intent (in ), optional :: delim
@@ -216,20 +250,19 @@ pure function string_len_trim(strings) result(n)
216
250
217
251
end function string_len_trim
218
252
253
+ ! >Author: John S. Urban
254
+ ! !License: Public Domain
255
+ ! ! parse string on delimiter characters and store tokens into an allocatable array
219
256
subroutine split (input_line ,array ,delimiters ,order ,nulls )
220
- ! parse string on delimiter characters and store tokens into an allocatable array"
221
- ! Author: John S. Urban
222
- ! License: Public Domain
223
-
224
-
225
- ! given a line of structure " par1 par2 par3 ... parn " store each par(n) into a separate variable in array.
226
- ! o by default adjacent delimiters in the input string do not create an empty string in the output array
227
- ! o no quoting of delimiters is supported
228
- character (len=* ),intent (in ) :: input_line ! input string to tokenize
229
- character (len=* ),optional ,intent (in ) :: delimiters ! list of delimiter characters
230
- character (len=* ),optional ,intent (in ) :: order ! order of output array sequential|[reverse|right]
231
- character (len=* ),optional ,intent (in ) :: nulls ! return strings composed of delimiters or not ignore|return|ignoreend
232
- character (len= :),allocatable ,intent (out ) :: array(:) ! output array of tokens
257
+ ! ! given a line of structure " par1 par2 par3 ... parn " store each par(n) into a separate variable in array.
258
+ ! !
259
+ ! ! * by default adjacent delimiters in the input string do not create an empty string in the output array
260
+ ! ! * no quoting of delimiters is supported
261
+ character (len=* ),intent (in ) :: input_line ! ! input string to tokenize
262
+ character (len=* ),optional ,intent (in ) :: delimiters ! ! list of delimiter characters
263
+ character (len=* ),optional ,intent (in ) :: order ! ! order of output array sequential|[reverse|right]
264
+ character (len=* ),optional ,intent (in ) :: nulls ! ! return strings composed of delimiters or not ignore|return|ignoreend
265
+ character (len= :),allocatable ,intent (out ) :: array(:) ! ! output array of tokens
233
266
234
267
integer :: n ! max number of strings INPUT_LINE could split into if all delimiter
235
268
integer ,allocatable :: ibegin(:) ! positions in input string where tokens start
@@ -334,8 +367,8 @@ subroutine split(input_line,array,delimiters,order,nulls)
334
367
enddo
335
368
end subroutine split
336
369
370
+ ! > Returns string with characters in charset replaced with target_char.
337
371
pure function replace (string , charset , target_char ) result(res)
338
- ! Returns string with characters in charset replaced with target_char.
339
372
character (* ), intent (in ) :: string
340
373
character , intent (in ) :: charset(:), target_char
341
374
character (len (string)) :: res
@@ -348,6 +381,7 @@ pure function replace(string, charset, target_char) result(res)
348
381
end do
349
382
end function replace
350
383
384
+ ! > increase the size of a TYPE(STRING_T) array by N elements
351
385
subroutine resize_string (list , n )
352
386
! > Instance of the array to be resized
353
387
type (string_t), allocatable , intent (inout ) :: list(:)
@@ -383,14 +417,14 @@ subroutine resize_string(list, n)
383
417
384
418
end subroutine resize_string
385
419
386
- pure function join ( str , sep , trm , left , right , start , end ) result (string)
387
- ! >
388
- ! !##NAME
420
+ ! >AUTHOR: John S. Urban
421
+ ! !LICENSE: Public Domain
422
+ ! !## NAME
389
423
! ! join(3f) - [fpm_strings:EDITING] append CHARACTER variable array into
390
424
! ! a single CHARACTER variable with specified separator
391
425
! ! (LICENSE:PD)
392
426
! !
393
- ! !##SYNOPSIS
427
+ ! !## SYNOPSIS
394
428
! !
395
429
! ! pure function join(str,sep,trm,left,right,start,end) result (string)
396
430
! !
@@ -403,13 +437,13 @@ pure function join(str,sep,trm,left,right,start,end) result (string)
403
437
! ! character(len=*),intent(in),optional :: end
404
438
! ! character(len=:),allocatable :: string
405
439
! !
406
- ! !##DESCRIPTION
407
- ! ! JOIN(3f) appends the elements of a CHARACTER array into a single
408
- ! ! CHARACTER variable, with elements 1 to N joined from left to right.
409
- ! ! By default each element is trimmed of trailing spaces and the
410
- ! ! default separator is a null string.
440
+ ! !## DESCRIPTION
441
+ ! ! JOIN(3f) appends the elements of a CHARACTER array into a single
442
+ ! ! CHARACTER variable, with elements 1 to N joined from left to right.
443
+ ! ! By default each element is trimmed of trailing spaces and the
444
+ ! ! default separator is a null string.
411
445
! !
412
- ! !##OPTIONS
446
+ ! !## OPTIONS
413
447
! ! STR(:) array of CHARACTER variables to be joined
414
448
! ! SEP separator string to place between each variable. defaults
415
449
! ! to a null string.
@@ -420,50 +454,47 @@ pure function join(str,sep,trm,left,right,start,end) result (string)
420
454
! ! TRM option to trim each element of STR of trailing
421
455
! ! spaces. Defaults to .TRUE.
422
456
! !
423
- ! !##RESULT
457
+ ! !## RESULT
424
458
! ! STRING CHARACTER variable composed of all of the elements of STR()
425
459
! ! appended together with the optional separator SEP placed
426
460
! ! between the elements.
427
461
! !
428
- ! !##EXAMPLE
462
+ ! !## EXAMPLE
429
463
! !
430
464
! ! Sample program:
431
- ! !
432
- ! ! program demo_join
433
- ! ! use fpm_strings, only: join
434
- ! ! implicit none
435
- ! ! character(len=:),allocatable :: s(:)
436
- ! ! character(len=:),allocatable :: out
437
- ! ! integer :: i
438
- ! ! s=[character(len=10) :: 'United',' we',' stand,', &
439
- ! ! & ' divided',' we fall.']
440
- ! ! out=join(s)
441
- ! ! write(*,'(a)') out
442
- ! ! write(*,'(a)') join(s,trm=.false.)
443
- ! ! write(*,'(a)') (join(s,trm=.false.,sep='|'),i=1,3)
444
- ! ! write(*,'(a)') join(s,sep='<>')
445
- ! ! write(*,'(a)') join(s,sep=';',left='[',right=']')
446
- ! ! write(*,'(a)') join(s,left='[',right=']')
447
- ! ! write(*,'(a)') join(s,left='>>')
448
- ! ! end program demo_join
465
+ ! !```fortran
466
+ ! ! program demo_join
467
+ ! ! use fpm_strings, only: join
468
+ ! ! implicit none
469
+ ! ! character(len=:),allocatable :: s(:)
470
+ ! ! character(len=:),allocatable :: out
471
+ ! ! integer :: i
472
+ ! ! s=[character(len=10) :: 'United',' we',' stand,', &
473
+ ! ! & ' divided',' we fall.']
474
+ ! ! out=join(s)
475
+ ! ! write(*,'(a)') out
476
+ ! ! write(*,'(a)') join(s,trm=.false.)
477
+ ! ! write(*,'(a)') (join(s,trm=.false.,sep='|'),i=1,3)
478
+ ! ! write(*,'(a)') join(s,sep='<>')
479
+ ! ! write(*,'(a)') join(s,sep=';',left='[',right=']')
480
+ ! ! write(*,'(a)') join(s,left='[',right=']')
481
+ ! ! write(*,'(a)') join(s,left='>>')
482
+ ! ! end program demo_join
483
+ ! !```fortran
449
484
! !
450
485
! ! Expected output:
451
486
! !
452
- ! ! United we stand, divided we fall.
453
- ! ! United we stand, divided we fall.
454
- ! ! United | we | stand, | divided | we fall.
455
- ! ! United | we | stand, | divided | we fall.
456
- ! ! United | we | stand, | divided | we fall.
457
- ! ! United<> we<> stand,<> divided<> we fall.
458
- ! ! [United];[ we];[ stand,];[ divided];[ we fall.]
459
- ! ! [United][ we][ stand,][ divided][ we fall.]
460
- ! ! >>United>> we>> stand,>> divided>> we fall.
461
- ! !
462
- ! !##AUTHOR
463
- ! ! John S. Urban
487
+ ! ! United we stand, divided we fall.
488
+ ! ! United we stand, divided we fall.
489
+ ! ! United | we | stand, | divided | we fall.
490
+ ! ! United | we | stand, | divided | we fall.
491
+ ! ! United | we | stand, | divided | we fall.
492
+ ! ! United<> we<> stand,<> divided<> we fall.
493
+ ! ! [United];[ we];[ stand,];[ divided];[ we fall.]
494
+ ! ! [United][ we][ stand,][ divided][ we fall.]
495
+ ! ! >>United>> we>> stand,>> divided>> we fall.
464
496
! !
465
- ! !##LICENSE
466
- ! ! Public Domain
497
+ pure function join (str ,sep ,trm ,left ,right ,start ,end ) result (string)
467
498
468
499
! @(#)join(3f): append an array of character variables with specified separator into a single CHARACTER variable
469
500
@@ -503,29 +534,29 @@ pure function join(str,sep,trm,left,right,start,end) result (string)
503
534
if (present (end))string= string// end
504
535
end function join
505
536
506
- function glob ( tame , wild )
507
- ! >
508
- ! !##NAME
537
+ ! >##AUTHOR John S. Urban
538
+ ! !##LICENSE Public Domain
539
+ ! !## NAME
509
540
! ! glob(3f) - [fpm_strings:COMPARE] compare given string for match to
510
541
! ! pattern which may contain wildcard characters
511
542
! ! (LICENSE:PD)
512
543
! !
513
- ! !##SYNOPSIS
544
+ ! !## SYNOPSIS
514
545
! !
515
546
! ! logical function glob(string, pattern )
516
547
! !
517
548
! ! character(len=*),intent(in) :: string
518
549
! ! character(len=*),intent(in) :: pattern
519
550
! !
520
- ! !##DESCRIPTION
521
- ! ! glob(3f) compares given STRING for match to PATTERN which may
522
- ! ! contain wildcard characters.
551
+ ! !## DESCRIPTION
552
+ ! ! glob(3f) compares given STRING for match to PATTERN which may
553
+ ! ! contain wildcard characters.
523
554
! !
524
- ! ! In this version to get a match the entire string must be described
525
- ! ! by PATTERN. Trailing whitespace is significant, so trim the input
526
- ! ! string to have trailing whitespace ignored.
555
+ ! ! In this version to get a match the entire string must be described
556
+ ! ! by PATTERN. Trailing whitespace is significant, so trim the input
557
+ ! ! string to have trailing whitespace ignored.
527
558
! !
528
- ! !##OPTIONS
559
+ ! !## OPTIONS
529
560
! ! string the input string to test to see if it contains the pattern.
530
561
! ! pattern the following simple globbing options are available
531
562
! !
@@ -537,7 +568,7 @@ function glob(tame,wild)
537
568
! ! o There is no escape character, so matching strings with
538
569
! ! literal question mark and asterisk is problematic.
539
570
! !
540
- ! !##EXAMPLES
571
+ ! !## EXAMPLES
541
572
! !
542
573
! ! Example program
543
574
! !
@@ -729,21 +760,18 @@ function glob(tame,wild)
729
760
! !
730
761
! ! Expected output
731
762
! !
732
- ! !##AUTHOR
733
- ! ! John S. Urban
734
763
! !
735
- ! !##REFERENCE
764
+ ! !## REFERENCE
736
765
! ! The article "Matching Wildcards: An Empirical Way to Tame an Algorithm"
737
766
! ! in Dr Dobb's Journal, By Kirk J. Krauss, October 07, 2014
738
767
! !
739
- ! !##LICENSE
740
- ! ! Public Domain
768
+ function glob (tame ,wild )
741
769
742
770
! @(#)fpm_strings::glob(3f): function compares text strings, one of which can have wildcards ('*' or '?').
743
771
744
- logical :: glob
745
- character (len=* ) :: tame ! A string without wildcards
746
- character (len=* ) :: wild ! A (potentially) corresponding string with wildcards
772
+ logical :: glob ! ! result of test
773
+ character (len=* ) :: tame ! ! A string without wildcards to compare to the globbing expression
774
+ character (len=* ) :: wild ! ! A (potentially) corresponding string with wildcards
747
775
character (len= len (tame)+ 1 ) :: tametext
748
776
character (len= len (wild)+ 1 ) :: wildtext
749
777
character (len= 1 ),parameter :: NULL= char (0 )
@@ -829,8 +857,8 @@ function glob(tame,wild)
829
857
enddo
830
858
end function glob
831
859
860
+ ! > Returns the length of the string representation of 'i'
832
861
pure integer function str_int_len(i) result(sz)
833
- ! Returns the length of the string representation of 'i'
834
862
integer , intent (in ) :: i
835
863
integer , parameter :: MAX_STR = 100
836
864
character (MAX_STR) :: s
@@ -840,15 +868,15 @@ pure integer function str_int_len(i) result(sz)
840
868
sz = len_trim (s)
841
869
end function
842
870
871
+ ! > Converts integer "i" to string
843
872
pure function str_int (i ) result(s)
844
- ! Converts integer "i" to string
845
873
integer , intent (in ) :: i
846
874
character (len= str_int_len(i)) :: s
847
875
write (s, ' (i0)' ) i
848
876
end function
849
877
878
+ ! > Returns the length of the string representation of 'i'
850
879
pure integer function str_int64_len(i) result(sz)
851
- ! Returns the length of the string representation of 'i'
852
880
integer (int64), intent (in ) :: i
853
881
integer , parameter :: MAX_STR = 100
854
882
character (MAX_STR) :: s
@@ -858,15 +886,15 @@ pure integer function str_int64_len(i) result(sz)
858
886
sz = len_trim (s)
859
887
end function
860
888
889
+ ! > Converts integer "i" to string
861
890
pure function str_int64 (i ) result(s)
862
- ! Converts integer "i" to string
863
891
integer (int64), intent (in ) :: i
864
892
character (len= str_int64_len(i)) :: s
865
893
write (s, ' (i0)' ) i
866
894
end function
867
895
896
+ ! > Returns the length of the string representation of 'l'
868
897
pure integer function str_logical_len(l) result(sz)
869
- ! Returns the length of the string representation of 'l'
870
898
logical , intent (in ) :: l
871
899
if (l) then
872
900
sz = 6
@@ -875,8 +903,8 @@ pure integer function str_logical_len(l) result(sz)
875
903
end if
876
904
end function
877
905
906
+ ! > Converts logical "l" to string
878
907
pure function str_logical (l ) result(s)
879
- ! Converts logical "l" to string
880
908
logical , intent (in ) :: l
881
909
character (len= str_logical_len(l)) :: s
882
910
if (l) then
0 commit comments