Soil Water Balance (SWB2)
Loading...
Searching...
No Matches
fstring.F90
Go to the documentation of this file.
1module fstring
2
3 use iso_c_binding, only : c_int, c_long_long, c_float, c_double, c_bool, &
4 c_short, c_null_char
5 implicit none
6
7 private
8
9 public :: operator(+)
10 interface operator(+)
11 procedure :: concatenate_char_char_fn
12 procedure :: concatenate_char_int_fn
13 procedure :: concatenate_char_float_fn
14 procedure :: concatenate_char_double_fn
15 end interface operator(+)
16
17 ! interface assignment(=)
18 ! procedure :: integer_to_char_sub
19 ! procedure :: float_to_char_sub
20 ! procedure :: double_to_char_sub
21 ! end interface assignment(=)
22
23 public :: operator( .strequal. )
24 interface operator( .strequal. )
25 procedure :: is_char_equal_to_char_case_sensitive_fn
26 end interface operator( .strequal. )
27
28 public :: operator( .strapprox. )
29 interface operator( .strapprox. )
30 procedure :: is_char_equal_to_char_case_insensitive_fn
31 end interface operator( .strapprox. )
32
33 public :: operator( .contains. )
34 interface operator( .contains. )
35 procedure :: is_string2_present_in_string1_case_sensitive_fn
36 end interface operator( .contains. )
37
38 public :: operator( .containssimilar. )
39 interface operator( .containssimilar. )
40 procedure :: is_string2_present_in_string1_case_insensitive_fn
41 end interface operator( .containssimilar. )
42
43 public :: ascharacter
44 interface ascharacter
45 procedure :: short_to_char_fn
46 procedure :: int_to_char_fn
47 procedure :: long_long_to_char_fn
48 procedure :: float_to_char_fn
49 procedure :: double_to_char_fn
50 procedure :: bool_to_char_fn
51 end interface ascharacter
52
53
54 public :: as_character
55 interface as_character
56 procedure :: short_to_char_fn
57 procedure :: int_to_char_fn
58 procedure :: long_long_to_char_fn
59 procedure :: float_to_char_fn
60 procedure :: double_to_char_fn
61 procedure :: bool_to_char_fn
62 end interface as_character
63
64 public :: as_integer
65 interface as_integer
66 procedure :: string_to_integer_fn
67 end interface as_integer
68
69 public :: as_float
70 interface as_float
71 procedure :: string_to_float_fn
72 end interface as_float
73
74 public :: chomp
75 interface chomp
76 procedure :: split_and_return_text_sub
77 end interface chomp
78
79 public :: fieldcount
80 interface fieldcount
81 procedure :: count_number_of_fields_fn
82 end interface fieldcount
83
84 public :: clean
85 interface clean
86 procedure :: remove_multiple_characters_fn
87 end interface clean
88
89 public :: squote
90 interface squote
91 procedure :: squote_char_fn
92 end interface squote
93
94 public :: dquote
95 interface dquote
96 procedure :: dquote_char_fn
97 end interface dquote
98
99 public :: replace
100 interface replace
101 procedure :: replace_character_sub
102 end interface replace
103
104 public :: asuppercase
105 interface asuppercase
106 procedure :: char_to_uppercase_fn
107 end interface asuppercase
108
109 public :: aslowercase
110 interface aslowercase
111 procedure :: char_to_lowercase_fn
112 end interface aslowercase
113
114 public :: touppercase
115 interface touppercase
116 procedure :: char_to_uppercase_sub
117 end interface touppercase
118
119 public :: tolowercase
120 interface tolowercase
121 procedure :: char_to_lowercase_sub
122 end interface tolowercase
123
124 public :: as_uppercase
125 interface as_uppercase
126 procedure :: char_to_uppercase_fn
127 end interface as_uppercase
128
129 public :: as_lowercase
130 interface as_lowercase
131 procedure :: char_to_lowercase_fn
132 end interface as_lowercase
133
134 public :: to_uppercase
135 interface to_uppercase
136 procedure :: char_to_uppercase_sub
137 end interface to_uppercase
138
139 public :: to_lowercase
140 interface to_lowercase
141 procedure :: char_to_lowercase_sub
142 end interface to_lowercase
143
144 public :: right
145 interface right
146 procedure :: return_right_part_of_string_fn
147 end interface right
148
149 public :: left
150 interface left
151 procedure :: return_left_part_of_string_fn
152 end interface left
153
155 procedure :: strip_full_pathname_fn
156 end interface strip_full_pathname
157
158 public :: f_to_c_str
159 interface f_to_c_str
160 procedure :: f_to_c_string_fn
161 end interface f_to_c_str
162
163 public :: c_to_f_str
164 interface c_to_f_str
165 procedure :: c_to_f_string_fn
166 end interface c_to_f_str
167
168 ! [ special ASCII characters ]
171 character (len=1), parameter :: tab = achar(9)
172 character (len=2), parameter :: whitespace = " "//achar(9)
173 character (len=1), parameter :: backslash = achar(92)
174 character (len=1), parameter :: forwardslash = achar(47)
175 character (len=1), parameter :: carriage_return = achar(13)
176 character (len=3), parameter :: comment_characters = "#!%"
177 character (len=1), parameter :: double_quote = achar(34)
178 character (len=3), parameter :: punctuation = ",;:"
179
180 private :: na_int, na_float, na_double
181 integer (c_int), parameter :: na_int = - (huge(1_c_int)-1_c_int)
182 real (c_float), parameter :: na_float = - (huge(1._c_float)-1._c_float)
183 real (c_double), parameter :: na_double = - (huge(1._c_double)-1._c_double)
184
185contains
186
187 ! remove file path from a filename
188 function strip_full_pathname_fn( filename ) result(value)
189
190 character (len=*), intent(in) :: filename
191 character (len=:), allocatable :: value
192
193 if (filename .contains. "/") value = right( value, substring="/")
194 if (filename .contains. "\") value = right( value, substring="\")
195
196 end function strip_full_pathname_fn
197
198
199 impure elemental function string_to_integer_fn(text) result(value)
200
201 character (len=*), intent(in) :: text
202 integer (c_int) :: value
203
204 ! [ LOCALS ]
205 integer (c_int) :: op_status
206 character (len=:), allocatable :: temp_str
207 real (c_float) :: float_value
208
209 temp_str = keepnumeric(text)
210
211 ! if the cleaned up string appears to be a real value,
212 ! attempt to read as real and convert to int
213 if ( scan(temp_str, ".") /= 0 ) then
214
215 read(unit=temp_str, fmt=*, iostat=op_status) float_value
216 if (op_status == 0) value = int(float_value, c_int)
217
218 else
219
220 read(unit=temp_str, fmt=*, iostat=op_status) value
221
222 endif
223
224 if (op_status /= 0) value = na_int
225
226 end function string_to_integer_fn
227
228!--------------------------------------------------------------------------------------------------
229
230 impure elemental function string_to_float_fn(text) result(value)
231
232 character (len=*), intent(in) :: text
233 real (c_float) :: value
234
235 ! [ LOCALS ]
236 integer (c_int) :: op_status
237 character (len=:), allocatable :: temp_str
238
239 temp_str = keepnumeric(text)
240
241 read(unit=temp_str, fmt=*, iostat=op_status) value
242 if (op_status /= 0) value = na_float
243
244 end function string_to_float_fn
245
246!--------------------------------------------------------------------------------------------------
247
248 function return_left_part_of_string_fn( string, indx, substring ) result( left_part )
249
250 character (len=*), intent(in) :: string
251 integer (c_int), intent(in), optional :: indx
252 character (len=*), intent(in), optional :: substring
253 character (len=:), allocatable :: left_part
254
255 ! [ LOCALS ]
256 integer (c_int) :: position
257
258 if ( present( indx ) ) then
259
260 if ( ( indx > 0 ) .and. ( indx < len_trim( string ) ) ) then
261
262 left_part = string( 1:indx )
263
264 else
265
266 left_part = "<NA>"
267
268 endif
269
270 elseif ( present( substring ) ) then
271
272 position = index( string, substring )
273
274 if ( position > 0 ) then
275
276 left_part = string( 1:(position-1) )
277
278 else
279
280 left_part = "<NA>"
281
282 endif
283
284 else
285
286 left_part = "<NA>"
287
288 endif
289
290
292
293!--------------------------------------------------------------------------------------------------
294
295 function return_right_part_of_string_fn( string, indx, substring ) result( right_part )
296
297 character (len=*), intent(in) :: string
298 integer (c_int), intent(in), optional :: indx
299 character (len=*), intent(in), optional :: substring
300 character (len=:), allocatable :: right_part
301
302 ! [ LOCALS ]
303 integer (c_int) :: position
304
305 if ( present( indx ) ) then
306
307 if ( ( indx > 0 ) .and. ( indx < len_trim( string ) ) ) then
308
309 right_part = string( (indx+1):len_trim(string) )
310
311 else
312
313 right_part = "<NA>"
314
315 endif
316
317 elseif ( present( substring ) ) then
318
319 position = index( string, substring, back=.true._c_bool )
320
321 if ( position > 0 ) then
322
323 right_part = string( (position+1):len_trim(string) )
324
325 else
326
327 right_part = "<NA>"
328
329 endif
330
331 else
332
333 right_part = "<NA>"
334
335 endif
336
337
339
340 !--------------------------------------------------------------------------------------------------
341
342 function is_string2_present_in_string1_case_insensitive_fn(sText1, sText2) result(lBool)
343
344 character (len=*), intent(in) :: stext1
345 character (len=*), intent(in) :: stext2
346 logical (c_bool) :: lbool
347
348 ! [ LOCALS ]
349 character (len=len_trim(sText1)) :: stemp1
350 character (len=len_trim(sText2)) :: stemp2
351
352 lbool = .false._c_bool
353
354 stemp1 = asuppercase(stext1)
355 stemp2 = asuppercase(stext2)
356
357 if ( index(stemp1, stemp2) /= 0 ) lbool = .true._c_bool
358
360
361 !--------------------------------------------------------------------------------------------------
362
363 function is_string2_present_in_string1_case_sensitive_fn(sText1, sText2) result(lBool)
364
365 character (len=*), intent(in) :: stext1
366 character (len=*), intent(in) :: stext2
367 logical (c_bool) :: lbool
368
369 ! [ LOCALS ]
370 character (len=len_trim(sText1)) :: stemp1
371 character (len=len_trim(sText2)) :: stemp2
372
373 lbool = .false._c_bool
374
375 stemp1 = trim( stext1 )
376 stemp2 = trim( stext2 )
377
378 if ( index(stemp1, stemp2) /= 0 ) lbool = .true._c_bool
379
381
382 !--------------------------------------------------------------------------------------------------
383
384 function is_char_equal_to_char_case_sensitive_fn(sText1, sText2) result(lBool)
385
386 character (len=*), intent(in) :: stext1
387 character (len=*), intent(in) :: stext2
388 logical (c_bool) :: lbool
389
390 ! [ LOCALS ]
391 character (len=:), allocatable :: stemp1
392 character (len=:), allocatable :: stemp2
393
394 lbool = .false._c_bool
395
396 stemp1 = trim( stext1 )
397 stemp2 = trim( stext2 )
398
399 if (trim(adjustl( stemp1 ) ) .eq. trim(adjustl( stemp2) ) ) lbool = .true._c_bool
400
402
403 !--------------------------------------------------------------------------------------------------
404
405 function is_char_equal_to_char_case_insensitive_fn(sText1, sText2) result(lBool)
406
407 character (len=*), intent(in) :: stext1
408 character (len=*), intent(in) :: stext2
409 logical (c_bool) :: lbool
410
411 ! [ LOCALS ]
412 character (len=:), allocatable :: stemp1
413 character (len=:), allocatable :: stemp2
414
415 lbool = .false._c_bool
416
417 stemp1 = asuppercase( stext1 )
418 stemp2 = asuppercase( stext2 )
419
420 if (trim(adjustl( stemp1 ) ) .eq. trim(adjustl( stemp2) ) ) lbool = .true._c_bool
421
423
424 !--------------------------------------------------------------------------------------------------
425
426 function concatenate_char_char_fn(sText1, sText2) result(sText)
427
428 character (len=*), intent(in) :: stext1
429 character (len=*), intent(in) :: stext2
430 character (len=:), allocatable :: stext
431
432 stext = stext1 // stext2
433
434 end function concatenate_char_char_fn
435
436 !--------------------------------------------------------------------------------------------------
437
438 function concatenate_char_int_fn(sText1, iValue1) result(sText)
439
440 character (len=*), intent(in) :: stext1
441 integer (c_int), intent(in) :: ivalue1
442 character (len=:), allocatable :: stext
443
444 stext = stext1 // ascharacter( ivalue1 )
445
446 end function concatenate_char_int_fn
447
448 !--------------------------------------------------------------------------------------------------
449
450 function concatenate_char_float_fn(sText1, fValue1) result(sText)
451
452 character (len=*), intent(in) :: stext1
453 real (c_float), intent(in) :: fvalue1
454 character (len=:), allocatable :: stext
455
456 stext = stext1 // ascharacter( fvalue1 )
457
458 end function concatenate_char_float_fn
459
460 !--------------------------------------------------------------------------------------------------
461
462 function concatenate_char_double_fn(sText1, dValue1) result(sText)
463
464 character (len=*), intent(in) :: stext1
465 real (c_double), intent(in) :: dvalue1
466 character (len=:), allocatable :: stext
467
468 stext = stext1 // ascharacter( dvalue1 )
469
470 end function concatenate_char_double_fn
471
472 !--------------------------------------------------------------------------------------------------
473 function short_to_char_fn(value, fmt_string) result(text)
474 integer (c_short), intent(in) :: value
475 character (len=*), intent(in), optional :: fmt_string
476 character (len=:), allocatable :: text
477
478 integer (c_int) :: status
479 character (len=32) :: sbuf
480
481 if ( present(fmt_string) ) then
482 write(sbuf, fmt="("//trim(fmt_string)//")", iostat=status) value
483 else
484 write(sbuf, fmt=*, iostat=status) value
485 endif
486
487 if (status==0) then
488 text = trim( adjustl(sbuf) )
489 else
490 text = "<NA>"
491 endif
492
493 end function short_to_char_fn
494
495!--------------------------------------------------------------------------------------------------
496
497 function int_to_char_fn(value, fmt_string) result(text)
498 integer (c_int), intent(in) :: value
499 character (len=*), intent(in), optional :: fmt_string
500 character (len=:), allocatable :: text
501
502 integer (c_int) :: status
503 character (len=32) :: sbuf
504
505 if ( present(fmt_string) ) then
506 write(sbuf, fmt="("//trim(fmt_string)//")", iostat=status) value
507 else
508 write(sbuf, fmt=*, iostat=status) value
509 endif
510
511 if (status==0) then
512 text = trim( adjustl(sbuf) )
513 else
514 text = "<NA>"
515 endif
516
517 end function int_to_char_fn
518
519!--------------------------------------------------------------------------------------------------
520
521 function long_long_to_char_fn(value, fmt_string) result(text)
522 integer (c_long_long), intent(in) :: value
523 character (len=*), intent(in), optional :: fmt_string
524 character (len=:), allocatable :: text
525
526 integer (c_int) :: status
527 character (len=32) :: sbuf
528
529 if ( present(fmt_string) ) then
530 write(sbuf, fmt="("//trim(fmt_string)//")", iostat=status) value
531 else
532 write(sbuf, fmt=*, iostat=status) value
533 endif
534
535 if (status==0) then
536 text = trim( adjustl(sbuf) )
537 else
538 text = "<NA>"
539 endif
540
541 end function long_long_to_char_fn
542
543!--------------------------------------------------------------------------------------------------
544
545 function float_to_char_fn(value, fmt_string) result(text)
546 real (c_float), intent(in) :: value
547 character (len=*), intent(in), optional :: fmt_string
548 character (len=:), allocatable :: text
549
550 integer (c_int) :: status
551 character (len=32) :: sbuf
552
553 if ( present(fmt_string) ) then
554 write(sbuf, fmt="("//trim(fmt_string)//")", iostat=status) value
555 else
556 write(sbuf, fmt=*, iostat=status) value
557 endif
558
559 if (status==0) then
560 text = trim( adjustl(sbuf) )
561 else
562 text = "<NA>"
563 endif
564
565 end function float_to_char_fn
566
567!--------------------------------------------------------------------------------------------------
568
569 function double_to_char_fn(value, fmt_string) result(text)
570 real (c_double), intent(in) :: value
571 character (len=*), intent(in), optional :: fmt_string
572 character (len=:), allocatable :: text
573
574 integer (c_int) :: status
575 character (len=32) :: sbuf
576
577 if ( present(fmt_string) ) then
578 write(sbuf, fmt="("//trim(fmt_string)//")", iostat=status) value
579 else
580 write(sbuf, fmt=*, iostat=status) value
581 endif
582
583 if (status==0) then
584 text = trim( adjustl(sbuf) )
585 else
586 text = "<NA>"
587 endif
588
589 end function double_to_char_fn
590
591!--------------------------------------------------------------------------------------------------
592
593 function bool_to_char_fn(value) result(text)
594 logical (c_bool), intent(in) :: value
595 character (len=:), allocatable :: text
596
597 integer (c_int) :: status
598 character (len=32) :: sbuf
599
600 if ( value ) then
601 text = ".TRUE._c_bool"
602 else
603 text = "False"
604 endif
605
606 end function bool_to_char_fn
607
608!--------------------------------------------------------------------------------------------------
609
610 function squote_char_fn(sText1) result(sText)
611
612 character (len=*), intent(in) :: stext1
613 character (len=:), allocatable :: stext
614
615 stext = "'"//trim(stext1)//"'"
616
617 end function squote_char_fn
618
619!--------------------------------------------------------------------------------------------------
620
621 function dquote_char_fn(sText1) result(sText)
622
623 character (len=*), intent(in) :: stext1
624 character (len=:), allocatable :: stext
625
626 stext = '"'//trim(stext1)//'"'
627
628 end function dquote_char_fn
629
630 !--------------------------------------------------------------------------------------------------
631
632 function char_to_uppercase_fn ( s ) result(sText)
633
634 ! ARGUMENTS
635 character (len=*), intent(in) :: s
636 character(len=len(s)) :: stext
637
638 ! LOCALS
639 integer (c_int) :: i ! do loop index
640
641 ! CONSTANTS
642 integer (c_int), parameter :: lower_to_upper = -32
643 integer (c_int), parameter :: ascii_small_a = ichar("a")
644 integer (c_int), parameter :: ascii_small_z = ichar("z")
645
646 stext = s
647
648 do i=1,len_trim(stext)
649 if ( ichar(stext(i:i) ) >= ascii_small_a .and. ichar(stext(i:i)) <= ascii_small_z ) then
650 stext(i:i) = char( ichar( stext(i:i) ) + lower_to_upper )
651 end if
652 end do
653
654 end function char_to_uppercase_fn
655
656 !--------------------------------------------------------------------------
657
658 function char_to_lowercase_fn ( s ) result(sText)
659
660 ! ARGUMENTS
661 character (len=*), intent(in) :: s
662 character(len=len(s)) :: stext
663
664 ! LOCALS
665 integer (c_int) :: i ! do loop index
666 ! CONSTANTS
667 integer (c_int), parameter :: upper_to_lower = 32
668 integer (c_int), parameter :: ascii_a = ichar("A")
669 integer (c_int), parameter :: ascii_z = ichar("Z")
670
671 stext = s
672
673 do i=1,len_trim(stext)
674 if ( ichar(stext(i:i) ) >= ascii_a .and. ichar(stext(i:i)) <= ascii_z ) then
675 stext(i:i) = char( ichar( stext(i:i) ) + upper_to_lower )
676 end if
677 end do
678
679 end function char_to_lowercase_fn
680
681
682 subroutine char_to_uppercase_sub ( s )
683
684 ! ARGUMENTS
685 character (len=*), intent(inout) :: s
686 ! LOCALS
687 integer (c_int) :: i ! do loop index
688 ! CONSTANTS
689 integer (c_int), parameter :: LOWER_TO_UPPER = -32
690 integer (c_int), parameter :: ASCII_SMALL_A = ichar("a")
691 integer (c_int), parameter :: ASCII_SMALL_Z = ichar("z")
692
693 do i=1,len_trim(s)
694 if ( ichar(s(i:i) ) >= ascii_small_a .and. ichar(s(i:i)) <= ascii_small_z ) then
695 s(i:i) = char( ichar( s(i:i) ) + lower_to_upper )
696 end if
697 end do
698
699 end subroutine char_to_uppercase_sub
700
701
702 subroutine char_to_lowercase_sub ( s )
703
704 ! ARGUMENTS
705 character (len=*), intent(inout) :: s
706 ! LOCALS
707 integer (c_int) :: i ! do loop index
708 ! CONSTANTS
709 integer (c_int), parameter :: UPPER_TO_LOWER = 32
710 integer (c_int), parameter :: ASCII_A = ichar("A")
711 integer (c_int), parameter :: ASCII_Z = ichar("Z")
712
713 ! UPPER_TO_LOWER = ichar( "a" ) - ichar( "A" )
714
715 do i=1,len_trim( s )
716 if ( ichar(s(i:i) ) >= ascii_a .and. ichar(s(i:i)) <= ascii_z ) then
717 s(i:i) = char( ichar( s(i:i) ) + upper_to_lower )
718 end if
719 end do
720
721 end subroutine char_to_lowercase_sub
722
723
724
725
726
727 !--------------------------------------------------------------------------
728
729
730 !> Strip offending characters from a text string.
731 !!
732 !! Remove unwanted characters from a text string. The target characters may optionally be supplied.
733 !! @param[in] sTextIn
734 impure function remove_multiple_characters_fn(sText1, sTargetCharacters) result(sText)
735
736 ! ARGUMENTS
737 character (len=*), intent(inout) :: stext1
738 character (len=*), intent(in), optional :: stargetcharacters
739 character (len=:), allocatable :: stext
740
741 ! LOCALS
742 character (len=512) :: sbuf
743 integer (c_int) :: ir ! Index in sRecord
744 integer (c_int) :: iindex1, iindex2
745 character (len=:), allocatable :: stargetcharacters_l
746
747 ! eliminate any leading spaces
748 stext1 = adjustl(stext1)
749 sbuf = ""
750 iindex2 = 0
751
752 if (present(stargetcharacters) ) then
753 stargetcharacters_l = stargetcharacters
754 else
755 stargetcharacters_l = ":/;,"
756 endif
757
758 do iindex1 = 1,len_trim(stext1)
759
760 ir = scan(stext1(iindex1:iindex1), stargetcharacters_l)
761
762 if(ir==0) then
763 iindex2 = iindex2 + 1
764 sbuf(iindex2:iindex2) = stext1(iindex1:iindex1)
765 end if
766
767 enddo
768
769 stext = trim(sbuf)
770
772
773 !--------------------------------------------------------------------------------------------------
774
775 !> Strip repeated characters from string.
776 !!
777 !! Remove repeated characters from a string. By default the function looks for repeated spaces and eliminates them.
778 !! @param[in] sTextIn
779 function remove_repeats(sText1, sChar) result(sText)
780
781 ! ARGUMENTS
782 character (len=*), intent(inout) :: stext1
783 character (len=*), intent(in), optional :: schar
784 character (len=:), allocatable :: stext
785
786 ! LOCALS
787 character (len=256) :: sbuf
788 integer (c_int) :: ir ! Index in sRecord
789 integer (c_int) :: iindex1, iindex2
790 character (len=1) :: schar_l
791 logical (c_bool) :: lpreviouslyfound
792
793 ! eliminate any leading spaces
794 stext1 = adjustl(stext1)
795 sbuf = ""
796 iindex2 = 0
797 lpreviouslyfound = .false._c_bool
798
799 if (present(schar) ) then
800 schar_l = schar
801 else
802 schar_l = " "
803 endif
804
805 do iindex1 = 1,len_trim(stext1)
806
807 ir = scan(stext1(iindex1:iindex1), schar_l)
808
809 if(ir==0) then
810 ! sChar_l was not found
811 iindex2 = iindex2 + 1
812 sbuf(iindex2:iindex2) = stext1(iindex1:iindex1)
813 lpreviouslyfound = .false._c_bool
814
815 elseif( lpreviouslyfound ) then
816 ! sChar_l was found, and was also found in the position preceding this one
817
818 ! No OP
819
820 else
821 ! sChar_l was found, but was *not* found in the preceding position
822
823 iindex2 = iindex2 + 1
824 sbuf(iindex2:iindex2) = stext1(iindex1:iindex1)
825 lpreviouslyfound = .true._c_bool
826
827 end if
828
829 enddo
830
831 stext = trim(sbuf)
832
833 end function remove_repeats
834
835 !--------------------------------------------------------------------------------------------------
836
837 function count_number_of_fields_fn( sText, sDelimiters ) result( iCount )
838
839 character (len=*), intent(in) :: stext
840 character (len=*), intent(in), optional :: sdelimiters
841 integer (c_int) :: icount
842
843 ! [ LOCALS ]
844 character (len=len(sText)) :: str
845 character (len=len(sText)) :: substr
846 character (len=:), allocatable :: delimiter_chr_
847
848 if ( present(sdelimiters) ) then
849 delimiter_chr_=sdelimiters
850 else
851 delimiter_chr_ = whitespace
852 endif
853
854 icount = 0
855
856 str = stext
857
858 do
859 call chomp(str=str, substr=substr, delimiter_chr=delimiter_chr_ )
860
861 if ( len_trim( substr ) == 0 ) exit
862
863 icount = icount + 1
864
865 enddo
866
867 end function count_number_of_fields_fn
868
869 !--------------------------------------------------------------------------------------------------
870
871 subroutine split_and_return_text_sub(str, substr, delimiter_chr, remove_extra_delimiters)
872
873 character (len=*), intent(inout) :: str
874 character (len=*), intent(out) :: substr
875 character (len=*), intent(in), optional :: delimiter_chr
876 logical (c_bool), intent(in), optional :: remove_extra_delimiters
877
878 ! [ LOCALS ]
879 character (len=:), allocatable :: delimiter_chr_
880 logical (c_bool) :: remove_extra_delimiters_
881 integer (kind=c_int) :: iIndex
882 integer (c_int) :: n
883
884 if ( present(remove_extra_delimiters)) then
885 remove_extra_delimiters_ = remove_extra_delimiters
886 else
887 remove_extra_delimiters_ = .false._c_bool
888 endif
889
890 if ( present(delimiter_chr) ) then
891 select case (delimiter_chr)
892 case ("WHITESPACE")
893 delimiter_chr_ = whitespace
894 case ("TAB", "TABS")
895 delimiter_chr_ = tab
896 case ("COMMA", "CSV")
897 delimiter_chr_ = ","
898 case default
899 delimiter_chr_ = delimiter_chr
900 end select
901 else
902 delimiter_chr_ = whitespace
903 endif
904
905 str = adjustl(str)
906
907 iindex = scan( string = str, set = delimiter_chr_ )
908
909 if (iindex == 0) then
910 ! no delimiters found; return string as was supplied originally
911 substr = str
912 str = ""
913 else
914 ! delimiters were found; split and return the chunks of text
915 substr = trim( str(1:iindex-1) )
916 str = trim( str(iindex + 1: ) )
917 ! inelegant, but something like this is needed to detect the presence of duplicate delimiters in cases where
918 ! more than one delimiter in a row should just be ignored
919 if (remove_extra_delimiters_) then
920 do
921 n = len_trim(str)
922 if (n == 0 ) exit
923 ! if we still have delimiters (whitespace, for example) in the first position, lop it off and try again
924 if ( scan( string=str(1:1), set=delimiter_chr_) == 0) exit
925 str = trim(str(2:n))
926 enddo
927 endif
928 endif
929
930 end subroutine split_and_return_text_sub
931
932 !--------------------------------------------------------------------------------------------------
933
934 subroutine replace_character_sub(sText1, sFind, sReplace)
935
936 character (len=*), intent(inout) :: sText1
937 character (len=1), intent(in) :: sFind
938 character (len=1), intent(in), optional :: sReplace
939
940 ! [ LOCALS ]
941 integer (c_int) :: iIndex
942 integer (c_int) :: iCount
943 character (len=len_trim(sText1)) :: sText
944
945 stext = ""
946
947 if ( len(stext1) > 0 ) then
948
949 icount = 0
950 do iindex = 1, len_trim(stext1)
951 if ( stext1(iindex:iindex) .ne. sfind) then
952 icount = icount + 1
953 stext(icount:icount) = stext1(iindex:iindex)
954 else
955 if (present(sreplace)) then
956 icount = icount + 1
957 stext(icount:icount) = sreplace
958 endif
959 endif
960 enddo
961
962 endif
963
964 stext1 = trim(stext)
965
966 end subroutine replace_character_sub
967
968!--------------------------------------------------------------------------------------------------
969
970 impure elemental function keepnumeric(text) result(result_text)
971
972 ! ARGUMENTS
973 character (len=*), intent(in) :: text
974 character (len=len(text)) :: result_text
975
976 character (len=:), allocatable :: temp_str
977 character (len=512) :: temp_result
978
979 integer (c_int) :: n
980 integer (c_int) :: index1, index2
981 character (len=:), allocatable :: target_characters
982
983 ! target_character omits the period ("."): do not want a real value returned
984 ! as a funky integer (e.g. string "3.141" returned as integer 3141 )
985 target_characters = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM" &
986 //"!@#$%^&*()_+-={}[]|\:;'<,>?/~`'"//double_quote
987
988 temp_str = adjustl(text)
989 temp_result = ""
990 index2 = 0
991
992 do index1 = 1,len_trim(text)
993 n = scan(text(index1:index1), target_characters)
994 if(n==0) then
995 index2 = index2 + 1
996 temp_result(index2:index2) = text(index1:index1)
997 endif
998 enddo
999
1000 result_text = trim(temp_result)
1001
1002 end function keepnumeric
1003
1004!--------------------------------------------------------------------------------------------------
1005
1006 function c_to_f_string_fn(c_character_str) result(f_character_str)
1007
1008 character (len=*), intent(in) :: c_character_str
1009 character (len=:), allocatable :: f_character_str
1010
1011 integer (c_int) :: indx
1012
1013 f_character_str = c_character_str
1014
1015 do indx=1,len(c_character_str)
1016 if (c_character_str(indx:indx) == c_null_char) then
1017 f_character_str = c_character_str(1:indx-1)
1018 exit
1019 endif
1020 enddo
1021
1022 end function c_to_f_string_fn
1023
1024!--------------------------------------------------------------------------------------------------
1025
1026 function f_to_c_string_fn(f_character_str) result(c_character_str)
1027
1028 character (len=*), intent(in) :: f_character_str
1029 character (len=:), allocatable :: c_character_str
1030
1031 integer (c_int) :: str_len
1032
1033 str_len = len_trim(f_character_str)
1034
1035 if ( str_len == 0 ) then
1036 c_character_str = c_null_char
1037 elseif ( f_character_str(str_len:str_len) == c_null_char ) then
1038 ! already has a null character at end; do not append another
1039 c_character_str = trim(f_character_str)
1040 else
1041 ! last char is not null character; append c_null_char
1042 c_character_str = trim(f_character_str)//c_null_char
1043 endif
1044
1045 end function f_to_c_string_fn
1046
1047
1048end module fstring
character(len=1), parameter, public forwardslash
Definition fstring.F90:174
impure elemental integer(c_int) function string_to_integer_fn(text)
Definition fstring.F90:200
character(len=:) function, allocatable int_to_char_fn(value, fmt_string)
Definition fstring.F90:498
logical(c_bool) function is_string2_present_in_string1_case_insensitive_fn(stext1, stext2)
Definition fstring.F90:343
character(len=:) function, allocatable dquote_char_fn(stext1)
Definition fstring.F90:622
character(len=len(s)) function char_to_lowercase_fn(s)
Definition fstring.F90:659
character(len=:) function, allocatable remove_repeats(stext1, schar)
Strip repeated characters from string.
Definition fstring.F90:780
impure character(len=:) function, allocatable remove_multiple_characters_fn(stext1, stargetcharacters)
Strip offending characters from a text string.
Definition fstring.F90:735
character(len=:) function, allocatable long_long_to_char_fn(value, fmt_string)
Definition fstring.F90:522
subroutine split_and_return_text_sub(str, substr, delimiter_chr, remove_extra_delimiters)
Definition fstring.F90:872
character(len=:) function, allocatable return_left_part_of_string_fn(string, indx, substring)
Definition fstring.F90:249
character(len=:) function, allocatable f_to_c_string_fn(f_character_str)
Definition fstring.F90:1027
integer(c_int), parameter, private na_int
Definition fstring.F90:181
character(len=:) function, allocatable concatenate_char_double_fn(stext1, dvalue1)
Definition fstring.F90:463
real(c_double), parameter, private na_double
Definition fstring.F90:183
character(len=:) function, allocatable short_to_char_fn(value, fmt_string)
Definition fstring.F90:474
character(len=3), parameter, public punctuation
Definition fstring.F90:178
character(len=:) function, allocatable squote_char_fn(stext1)
Definition fstring.F90:611
impure elemental real(c_float) function string_to_float_fn(text)
Definition fstring.F90:231
character(len=1), parameter, public carriage_return
Definition fstring.F90:175
logical(c_bool) function is_string2_present_in_string1_case_sensitive_fn(stext1, stext2)
Definition fstring.F90:364
character(len=1), parameter, public tab
Definition fstring.F90:171
character(len=:) function, allocatable concatenate_char_float_fn(stext1, fvalue1)
Definition fstring.F90:451
character(len=:) function, allocatable float_to_char_fn(value, fmt_string)
Definition fstring.F90:546
logical(c_bool) function is_char_equal_to_char_case_insensitive_fn(stext1, stext2)
Definition fstring.F90:406
character(len=:) function, allocatable bool_to_char_fn(value)
Definition fstring.F90:594
character(len=:) function, allocatable double_to_char_fn(value, fmt_string)
Definition fstring.F90:570
subroutine char_to_lowercase_sub(s)
Definition fstring.F90:703
character(len=1), parameter, public backslash
Definition fstring.F90:173
subroutine replace_character_sub(stext1, sfind, sreplace)
Definition fstring.F90:935
integer(c_int) function count_number_of_fields_fn(stext, sdelimiters)
Definition fstring.F90:838
impure elemental character(len=len(text)) function keepnumeric(text)
Definition fstring.F90:971
character(len=len(s)) function char_to_uppercase_fn(s)
Definition fstring.F90:633
character(len=2), parameter, public whitespace
Definition fstring.F90:172
real(c_float), parameter, private na_float
Definition fstring.F90:182
character(len=:) function, allocatable concatenate_char_int_fn(stext1, ivalue1)
Definition fstring.F90:439
subroutine char_to_uppercase_sub(s)
Definition fstring.F90:683
character(len=:) function, allocatable c_to_f_string_fn(c_character_str)
Definition fstring.F90:1007
character(len=:) function, allocatable strip_full_pathname_fn(filename)
Definition fstring.F90:189
character(len=1), parameter, public double_quote
Definition fstring.F90:177
character(len=:) function, allocatable concatenate_char_char_fn(stext1, stext2)
Definition fstring.F90:427
logical(c_bool) function is_char_equal_to_char_case_sensitive_fn(stext1, stext2)
Definition fstring.F90:385
character(len=3), parameter, public comment_characters
Definition fstring.F90:176
character(len=:) function, allocatable return_right_part_of_string_fn(string, indx, substring)
Definition fstring.F90:296