Soil Water Balance (SWB2)
Loading...
Searching...
No Matches
fstring_list.F90
Go to the documentation of this file.
2
3 use iso_c_binding
4 use fstring
5 implicit none
6
7 private
8
9 public :: fstring_list_t
10
11 ! public :: operator(+)
12 ! interface operator(+)
13 ! module procedure :: concatenate_fstring_to_fstring_sub
14 ! end interface operator(+)
15 !
16 public :: assignment(=)
17 interface assignment(=)
18 module procedure :: assign_fstring_to_character_sub
19 end interface assignment(=)
20
22
23 character (len=:), allocatable :: s
24 integer (c_int) :: count = 0
25 integer (c_int) :: missing_value_count = 0
26
27 contains
28
30 generic :: assignment(=) => assign_character_to_fstring_sub
31
33 generic :: print_all => print_all_entries_sub
34
36 generic :: print => print_as_markdown_sub
37
41 generic :: append => append_character_to_fstring_sub, &
44
46 generic :: count_entries => count_strings_in_list_fn
47
52
54 generic :: get_integer => retrieve_values_as_integer_fn
55
57 generic :: get_float => retrieve_values_as_float_fn
58
60 generic :: get_double => retrieve_values_as_double_fn
61
63 generic :: get_logical => retrieve_values_as_logical_fn
64
67
68 procedure :: list_all_fn
69 generic :: list_all => list_all_fn
70
72 generic :: empty_entries_present => are_there_missing_list_values_fn
73
75 generic :: sort => quicksort_alpha_sub
76
77 procedure :: quicksort_int_sub
78 generic :: sort_integer => quicksort_int_sub
79
81 generic :: sort_float => quicksort_float_sub
82
83 procedure :: clear_list_sub
84 generic :: clear => clear_list_sub
85
87 generic :: count_matching => return_count_of_matching_strings_fn
88
89! procedure :: is_substring_present_in_string_case_sensitive_fn
90! procedure :: is_substring_present_in_string_case_insensitive_fn
91
94
97
100
101 end type fstring_list_t
102
103 public :: na_int, na_float, na_double
104 integer (c_int), parameter :: na_int = - (huge(1_c_int)-1_c_int)
105 real (c_float), parameter :: na_float = - (huge(1._c_float)-1._c_float)
106 real (c_double), parameter :: na_double = - (huge(1._c_double)-1._c_double)
107
108 public::split
109 interface split
110 module procedure :: split_character_into_fstring_list_fn
111 end interface split
112
113 public::create_list
114 interface create_list
115 module procedure :: split_character_into_fstring_list_fn
116 end interface create_list
117
119 integer (c_int) :: order
120 character (len=:), allocatable :: alpha_value
121 end type alpha_sort_group_t
122
124 integer (c_int) :: order
125 integer (c_int) :: int_value
126 end type int_sort_group_t
127
129 integer (c_int) :: order
130 real (c_float) :: float_value
131 end type float_sort_group_t
132
133contains
134
135!--------------------------------------------------------------------------------------------------
136
137 subroutine assign_character_to_fstring_sub(this, character_str)
138
139 class(fstring_list_t), intent(inout) :: this
140 character (len=*), intent(in) :: character_str
141
142 call this%clear()
143
144 this%s = f_to_c_str(character_str)
145 this%count = 1
146
148
149!--------------------------------------------------------------------------------------------------
150
151 subroutine assign_fstring_to_character_sub( character_str, string_list )
152
153 character (len=:), allocatable, intent(out) :: character_str
154 type (FSTRING_LIST_T), intent(in) :: string_list
155
156 character (len=:), allocatable :: temp_str
157
158 temp_str = string_list%get(1)
159 character_str = trim(temp_str)
160
162
163!--------------------------------------------------------------------------------------------------
164
165 function split_character_into_fstring_list_fn(character_str, delimiter_chr) result(new_fstring)
166
167 character (len=*), intent(in) :: character_str
168 character (len=1), intent(in), optional :: delimiter_chr
169 type (fstring_list_t) :: new_fstring
170
171 character (len=len(character_str)) :: string
172 character (len=len(character_str)) :: substring
173 character (len=1) :: delimiter_chr_
174 integer (c_int) :: num_delimiters
175 integer (c_int) :: i
176
177 if ( present(delimiter_chr) ) then
178 delimiter_chr_ = delimiter_chr
179 else
180 delimiter_chr_ = ","
181 endif
182
183 string = character_str
184 num_delimiters = 0
185
186 do i=1, len_trim(string)
187 if ( string(i:i) == delimiter_chr_ ) num_delimiters = num_delimiters + 1
188 enddo
189
190 if ( num_delimiters == 0 ) then
191
192 else
193
194! example: "one, two, three, four"
195! num_delimiters=3
196
197 do i=1, num_delimiters
198 call chomp(string, substring, delimiter_chr_)
199 call new_fstring%append( substring )
200 end do
201
202 call chomp(string, substring, delimiter_chr_)
203 call new_fstring%append( substring )
204
205 endif
206
208
209!--------------------------------------------------------------------------------------------------
210
211 function count_strings_in_list_fn(this) result(count)
212
213 class(fstring_list_t), intent(inout), target :: this
214 integer (c_int) :: count
215
216 integer (c_int) :: i
217
218 count = 0
219
220 do i=1, len_trim(this%s)
221 if( this%s(i:i) == c_null_char ) count = count + 1
222 enddo
223
224 end function count_strings_in_list_fn
225
226!--------------------------------------------------------------------------------------------------
227
228 subroutine append_character_to_fstring_sub(this, character_str)
229
230 class(fstring_list_t), intent(inout), target :: this
231 character (len=*), intent(in) :: character_str
232
233 if ( .not. allocated( this%s ) ) this%s = ""
234 this%s = trim(this%s)//trim(adjustl(f_to_c_str(character_str)))
235 if ( len_trim(character_str) == 0 ) &
236 this%missing_value_count = this%missing_value_count + 1
237 this%count = this%count + 1
238
240
241!--------------------------------------------------------------------------------------------------
242
243subroutine append_character_array_to_fstring_sub(this, character_str)
244
245 class(fstring_list_t), intent(inout), target :: this
246 character (len=*), intent(in) :: character_str(:)
247
248 integer (c_int) :: i
249
250 do i=1, size(character_str,1)
251
252 this%s = trim(this%s)//trim(adjustl(f_to_c_str(character_str(i))))
253 if ( len_trim(character_str(i)) == 0 ) &
254 this%missing_value_count = this%missing_value_count + 1
255 this%count = this%count + 1
256
257 enddo
258
260
261!--------------------------------------------------------------------------------------------------
262
263subroutine append_fstring_to_fstring_sub(this, other_fstring)
264
265 class(fstring_list_t), intent(inout), target :: this
266 type (FSTRING_LIST_T), intent(inout) :: other_fstring
267
268 integer (c_int) :: i
269 character (len=:), allocatable :: temp_str
270
271 do i=1, other_fstring%count
272
273 temp_str = other_fstring%get(i)
274 call this%append( other_fstring%get(i) )
275 if ( len_trim(temp_str) == 0 ) &
276 this%missing_value_count = this%missing_value_count + 1
277
278 enddo
279
281
282!--------------------------------------------------------------------------------------------------
283
284 function are_there_missing_list_values_fn(this) result(value)
285
286 class(fstring_list_t), intent(inout), target :: this
287 logical (c_bool) :: value
288
289 if ( this%missing_value_count > 0 ) then
290 value = .true._c_bool
291 else
292 value = .false._c_bool
293 endif
294
296
297!--------------------------------------------------------------------------------------------------
298
299 subroutine print_all_entries_sub(this)
300
301 class(fstring_list_t), intent(inout), target :: this
302
303 integer (c_int) :: start_pos
304 integer (c_int) :: end_pos
305 integer (c_int) :: str_len
306 integer (c_int) :: i
307
308 start_pos = 1
309 end_pos = index( this%s, c_null_char ) - 1
310 str_len = len_trim( this%s )
311
312 do i=1, this%count_entries()
313
314 write(*,fmt="(a)") this%s(start_pos:end_pos)
315
316 start_pos = end_pos + 2
317 end_pos = index( this%s(start_pos:str_len), c_null_char ) + start_pos - 2
318
319 end do
320
321 end subroutine print_all_entries_sub
322
323!--------------------------------------------------------------------------------------------------
324
325 subroutine clear_list_sub(this)
326
327 class(fstring_list_t), intent(inout) :: this
328
329 this%s = ""
330 this%count = 0
331
332 end subroutine clear_list_sub
333
334!--------------------------------------------------------------------------------------------------
335
336 function retrieve_values_as_integer_fn(this) result(values)
337
338 class(fstring_list_t), intent(inout), target :: this
339 integer (c_int), allocatable :: values(:)
340
341 integer (c_int) :: i
342 integer (c_int) :: value
343 integer (c_int) :: op_status
344 character (len=64) :: sbuf
345
346 if (this%count <= 0) then
347 allocate(values(1),stat=op_status)
348 values = na_int
349 else
350
351 allocate(values(this%count),stat=op_status)
352
353 do i=1,this%count
354 sbuf = this%get(i)
355 value = as_integer(sbuf)
356 if ( op_status==0 ) then
357 values(i) = value
358 else
359 values(i) = na_int
360 endif
361 enddo
362
363 endif
364
366
367!--------------------------------------------------------------------------------------------------
368
369 function retrieve_values_as_float_fn(this) result(values)
370
371 class(fstring_list_t), intent(inout), target :: this
372 real (c_float), allocatable :: values(:)
373
374 integer (c_int) :: i
375 real (c_float) :: value
376 integer (c_int) :: op_status
377 character (len=64) :: sbuf
378
379 if (this%count <= 0) then
380 allocate(values(1),stat=op_status)
381 values = na_float
382 else
383 allocate(values(this%count),stat=op_status)
384
385 do i=1,this%count
386 sbuf = this%get(i)
387 read(unit=sbuf, fmt=*, iostat=op_status) value
388 if ( op_status==0 ) then
389 values(i) = value
390 else
391 values(i) = na_float
392 endif
393 enddo
394
395 endif
396
397 end function retrieve_values_as_float_fn
398
399!--------------------------------------------------------------------------------------------------
400
401function retrieve_values_as_double_fn(this) result(values)
402
403 class(fstring_list_t), intent(inout), target :: this
404 real (c_double), allocatable :: values(:)
405
406 integer (c_int) :: i
407 real (c_double) :: value
408 integer (c_int) :: op_status
409 character (len=64) :: sbuf
410
411 if (this%count <=0) then
412
413 allocate(values(1),stat=op_status)
414 values = na_double
415
416 else
417
418 allocate(values(this%count),stat=op_status)
419
420 do i=1,this%count
421 sbuf = this%get(i)
422 read(unit=sbuf, fmt=*, iostat=op_status) value
423 if ( op_status==0 ) then
424 values(i) = value
425 else
426 values(i) = na_double
427 endif
428 enddo
429
430 endif
431
433
434!--------------------------------------------------------------------------------------------------
435
436function retrieve_values_as_logical_fn(this) result(values)
437
438 class(fstring_list_t), intent(inout) :: this
439 logical (c_bool), allocatable :: values(:)
440
441 integer (c_int) :: i
442 integer (c_int) :: op_status
443 character (len=64) :: sbuf
444
445 allocate(values(this%count),stat=op_status)
446
447 do i=1,this%count
448 sbuf = this%get(i)
449
450 select case(sbuf)
451
452 case("true","T","True","TRUE","1","Y","Yes","yes","YES")
453 values(i) = .true._c_bool
454 case default
455 values(i) = .false._c_bool
456
457 end select
458
459 enddo
460
462
463!--------------------------------------------------------------------------------------------------
464
465 pure function retrieve_value_from_list_at_index_fn(this, index_val) result(text)
466
467 class(fstring_list_t), intent(in) :: this
468 integer (c_int), intent(in) :: index_val
469 character(len=:), allocatable :: text
470
471 integer (c_int) :: start_pos
472 integer (c_int) :: end_pos
473 integer (c_int) :: str_len
474 integer (c_int) :: i
475
476 start_pos = 1
477 text = "<NA>"
478
479 if ( allocated(this%s) ) then
480
481 end_pos = index( this%s, c_null_char ) - 1
482 str_len = len_trim( this%s )
483
484 do i=1, this%count
485
486 if ( index_val == i ) then
487 text = this%s(start_pos:end_pos)
488 exit
489 endif
490
491 ! skip over the 'c_null_char' to position of beginning of
492 ! next substring
493 start_pos = end_pos + 2
494 end_pos = index( this%s(start_pos:str_len), c_null_char ) + start_pos - 2
495
496 end do
497
498 endif
499
501
502!--------------------------------------------------------------------------------------------------
503
504 subroutine replace_value_at_index_sub(this, index_val, character_str)
505
506 class(fstring_list_t), intent(inout) :: this
507 integer (c_int), intent(in) :: index_val
508 character(len=*) :: character_str
509
510 integer (c_int) :: i
511 type (FSTRING_LIST_T) :: temp_list
512
513
514 if (this%count > 0) then
515
516 do i=1, this%count
517 if ( index_val == i ) then
518 call temp_list%append(character_str)
519 else
520 call temp_list%append(this%get(i))
521 endif
522 end do
523
524 this%s = temp_list%s
525
526 endif
527
528 end subroutine replace_value_at_index_sub
529
530!--------------------------------------------------------------------------------------------------
531
532 function retrieve_values_for_range_of_indices_fn(this, start_indx, end_indx) result(text)
533
534 class(fstring_list_t), intent(inout) :: this
535 integer (c_int), intent(in) :: start_indx
536 integer (c_int), intent(in) :: end_indx
537 character (len=:), allocatable :: text
538
539 integer (c_int) :: i
540
541 if (this%count == 0) then
542 text = "<NA>"
543 else
544 do i=1, this%count
545 if (i == start_indx) then
546 text = trim(this%get(i))
547 elseif (i > start_indx .and. i <= end_indx ) then
548 text = trim(text)//" "//trim(this%get(i))
549 endif
550 enddo
551 endif
552
554
555!--------------------------------------------------------------------------------------------------
556
557 function list_all_fn(this, delimiter_chr) result( text )
558
559 class(fstring_list_t), intent(inout) :: this
560 character (len=1), intent(in), optional :: delimiter_chr
561 character (len=:), allocatable :: text
562
563 integer (c_int) :: i
564
565 if (this%count == 0) then
566 text = "<NA>"
567 elseif (present(delimiter_chr) ) then
568 text = trim(this%get(1))
569 do i=2, this%count
570 text = trim(text)//delimiter_chr//trim(this%get(i))
571 enddo
572 else
573 text = "(1) "//trim(this%get(1))
574 do i=2, this%count
575 text = trim(text)//" ("//as_character(i)//") "//trim(this%get(i))
576 enddo
577 endif
578
579 end function list_all_fn
580
581!--------------------------------------------------------------------------------------------------
582
583 subroutine quicksort_alpha_sub(this, sort_order)
584
585 class(fstring_list_t), intent(inout) :: this
586 character (len=*), intent(in), optional :: sort_order
587
588 type (ALPHA_SORT_GROUP_T), allocatable :: sort_group(:)
589 integer (c_int) :: i
590 integer (c_int) :: count
591 logical (c_bool) :: decreasing_order
592
593 decreasing_order = .false._c_bool
594
595 if ( present(sort_order) ) then
596 select case (sort_order)
597
598 case ("Decreasing","decreasing","DECREASING")
599 decreasing_order = .true._c_bool
600 end select
601 endif
602
603 count = this%count
604
605 allocate(sort_group(count))
606
607 ! create the 'sort_group' data structure
608 do i=1, count
609 sort_group(i)%order = i
610 sort_group(i)%alpha_value = this%get(i)
611 enddo
612
613 call qsort_alpha(sort_group, this%count)
614
615 ! wipe out previous values
616 call this%clear()
617
618 if ( decreasing_order ) then
619 ! copy sorted values back into list structure (DECREASING ORDER)
620 do i=count, 1, -1
621 call this%append(sort_group(i)%alpha_value)
622 enddo
623 else
624 ! copy sorted values back into list structure (INCREASING ORDER)
625 do i=1, count
626 call this%append(sort_group(i)%alpha_value)
627 enddo
628 endif
629
630 end subroutine quicksort_alpha_sub
631
632!-------------------------------------------------------------------------------------------------
633
634 subroutine quicksort_int_sub(this, sort_order)
635 class(fstring_list_t), intent(inout) :: this
636 character (len=*), intent(in), optional :: sort_order
637
638 type (INT_SORT_GROUP_T), allocatable :: sort_group(:)
639 integer (c_int), allocatable :: int_values(:)
640 integer (c_int) :: i
641 integer (c_int) :: count
642 logical (c_bool) :: decreasing_order
643
644 decreasing_order = .false._c_bool
645
646 if ( present(sort_order) ) then
647 select case (sort_order)
648 case ("Decreasing","decreasing","DECREASING")
649 decreasing_order = .true._c_bool
650 end select
651 endif
652
653 count = this%count
654
655 allocate(sort_group(count))
656 allocate(int_values(count))
657
658 int_values = this%get_integer()
659
660 ! create the 'sort_group' data structure
661 do i=1, count
662 sort_group(i)%order = i
663 sort_group(i)%int_value = int_values(i)
664 enddo
665
666 call qsort_int(sort_group, this%count)
667 ! wipe out previous values
668 call this%clear()
669 if ( decreasing_order ) then
670 ! copy sorted values back into list structure (DECREASING ORDER)
671 do i=count, 1, -1
672 call this%append( as_character(sort_group(i)%int_value) )
673 enddo
674 else
675 ! copy sorted values back into list structure (INCREASING ORDER)
676 do i=1, count
677 call this%append( as_character(sort_group(i)%int_value) )
678 enddo
679 endif
680 end subroutine quicksort_int_sub
681
682!-------------------------------------------------------------------------------------------------
683
684 subroutine quicksort_float_sub(this, sort_order)
685
686 class(fstring_list_t), intent(inout) :: this
687 character (len=*), intent(in), optional :: sort_order
688
689 type (FLOAT_SORT_GROUP_T), allocatable :: sort_group(:)
690 real (c_float), allocatable :: float_values(:)
691 integer (c_int) :: i
692 integer (c_int) :: count
693 logical (c_bool) :: decreasing_order
694
695 decreasing_order = .false._c_bool
696
697 if ( present(sort_order) ) then
698 select case (sort_order)
699
700 case ("Decreasing","decreasing","DECREASING")
701 decreasing_order = .true._c_bool
702 end select
703 endif
704
705 count = this%count
706
707 allocate(sort_group(count))
708
709 float_values = this%get_float()
710
711 ! create the 'sort_group' data structure
712 do i=1, count
713 sort_group(i)%order = i
714 sort_group(i)%float_value = float_values(i)
715 enddo
716
717 call qsort_float(sort_group, this%count)
718
719 ! wipe out previous values
720 call this%clear()
721
722 if ( decreasing_order ) then
723 ! copy sorted values back into list structure (DECREASING ORDER)
724 do i=count, 1, -1
725 call this%append( as_character(sort_group(i)%float_value) )
726 enddo
727 else
728 ! copy sorted values back into list structure (INCREASING ORDER)
729 do i=1, count
730 call this%append( as_character(sort_group(i)%float_value) )
731 enddo
732 endif
733
734 end subroutine quicksort_float_sub
735
736!-------------------------------------------------------------------------------------------------
737
738 recursive subroutine qsort_alpha(sort_group, nrec)
739
740 ! NOTE: this code based on code found here:
741 ! https://rosettacode.org/wiki/Sorting_algorithms/Quicksort#Fortran
742
743 ! DUMMY ARGUMENTS
744 type (alpha_sort_group_t), intent(inout) :: sort_group(:)
745 integer (c_int), intent(in) :: nrec
746
747 ! LOCAL VARIABLES
748 integer (c_int) :: left_indx, right_indx
749 real (c_float) :: random
750 character (len=:), allocatable :: pivot
751 type (alpha_sort_group_t) :: temp
752 integer (c_int) :: marker
753
754 if (nrec > 1) then
755
756 call random_number(random)
757 pivot = sort_group(int(random*real(nrec-1))+1)%alpha_value ! random pivor (not best performance, but avoids worst-case)
758 left_indx = 0
759 right_indx = nrec + 1
760
761 do while (left_indx < right_indx)
762 right_indx = right_indx - 1
763 do while (sort_group(right_indx)%alpha_value > pivot)
764 right_indx = right_indx - 1
765 end do
766 left_indx = left_indx + 1
767 do while (sort_group(left_indx)%alpha_value < pivot)
768 left_indx = left_indx + 1
769 end do
770 if (left_indx < right_indx) then
771 temp = sort_group(left_indx)
772 sort_group(left_indx) = sort_group(right_indx)
773 sort_group(right_indx) = temp
774 end if
775 end do
776
777 if (left_indx == right_indx) then
778 marker = left_indx + 1
779 else
780 marker = left_indx
781 end if
782
783 call qsort_alpha(sort_group(:marker-1),marker-1)
784 call qsort_alpha(sort_group(marker:),nrec-marker+1)
785
786 end if
787
788 end subroutine qsort_alpha
789
790!--------------------------------------------------------------------------------------------------
791
792 recursive subroutine qsort_int(sort_group, nrec)
793
794 ! NOTE: this code based on code found here:
795 ! https://rosettacode.org/wiki/Sorting_algorithms/Quicksort#Fortran
796
797 ! DUMMY ARGUMENTS
798 type (int_sort_group_t), intent(inout) :: sort_group(:)
799 integer (c_int), intent(in) :: nrec
800
801 ! LOCAL VARIABLES
802 integer (c_int) :: left_indx, right_indx
803 real (c_float) :: random
804 integer (c_int) :: pivot
805 type (int_sort_group_t) :: temp
806 integer (c_int) :: marker
807
808 if (nrec > 1) then
809
810 call random_number(random)
811 pivot = sort_group(int(random*real(nrec-1))+1)%int_value ! random pivor (not best performance, but avoids worst-case)
812 left_indx = 0
813 right_indx = nrec + 1
814
815 do while (left_indx < right_indx)
816 right_indx = right_indx - 1
817 do while (sort_group(right_indx)%int_value > pivot)
818 right_indx = right_indx - 1
819 end do
820 left_indx = left_indx + 1
821 do while (sort_group(left_indx)%int_value < pivot)
822 left_indx = left_indx + 1
823 end do
824 if (left_indx < right_indx) then
825 temp = sort_group(left_indx)
826 sort_group(left_indx) = sort_group(right_indx)
827 sort_group(right_indx) = temp
828 end if
829 end do
830
831 if (left_indx == right_indx) then
832 marker = left_indx + 1
833 else
834 marker = left_indx
835 end if
836
837 call qsort_int(sort_group(:marker-1),marker-1)
838 call qsort_int(sort_group(marker:),nrec-marker+1)
839
840 end if
841
842 end subroutine qsort_int
843
844!--------------------------------------------------------------------------------------------------
845
846 recursive subroutine qsort_float(sort_group, nrec)
847
848 ! NOTE: this code based on code found here:
849 ! https://rosettacode.org/wiki/Sorting_algorithms/Quicksort#Fortran
850
851 ! DUMMY ARGUMENTS
852 type (float_sort_group_t), intent(in out) :: sort_group(:)
853 integer (c_int), intent(in) :: nrec
854
855 ! LOCAL VARIABLES
856 integer (c_int) :: left_indx, right_indx
857 real (c_float) :: random
858 real (c_float) :: pivot
859 type (float_sort_group_t) :: temp
860 integer (c_int) :: marker
861
862 if (nrec > 1) then
863
864 call random_number(random)
865 pivot = sort_group(int(random*real(nrec-1))+1)%float_value ! random pivor (not best performance, but avoids worst-case)
866 left_indx = 0
867 right_indx = nrec + 1
868
869 do while (left_indx < right_indx)
870 right_indx = right_indx - 1
871 do while (sort_group(right_indx)%float_value > pivot)
872 right_indx = right_indx - 1
873 end do
874 left_indx = left_indx + 1
875 do while (sort_group(left_indx)%float_value < pivot)
876 left_indx = left_indx + 1
877 end do
878 if (left_indx < right_indx) then
879 temp = sort_group(left_indx)
880 sort_group(left_indx) = sort_group(right_indx)
881 sort_group(right_indx) = temp
882 end if
883 end do
884
885 if (left_indx == right_indx) then
886 marker = left_indx + 1
887 else
888 marker = left_indx
889 end if
890
891 call qsort_float(sort_group(:marker-1),marker-1)
892 call qsort_float(sort_group(marker:),nrec-marker+1)
893
894 end if
895
896 end subroutine qsort_float
897
898!--------------------------------------------------------------------------------------------------
899
900 pure function return_count_of_matching_strings_fn(this, substr, match_case) result(count)
901
902 class(fstring_list_t), intent(in) :: this
903 character (len=*), intent(in) :: substr
904
905 logical (c_bool), intent(in), optional :: match_case
906 integer (c_int) :: count
907
908 ! [ LOCALS ]
909 integer (c_int) :: i
910 logical (c_bool) :: match_case_
911
912 if ( present( match_case ) ) then
913 match_case_ = match_case
914 else
915 match_case_ = .false._c_bool
916 endif
917
918 count = 0
919
920 if ( match_case_ ) then
921
922 do i=1, this%count
923
924 if ( this%get(i) .strequal. substr ) count = count + 1
925
926 enddo
927
928 else
929
930 do i=1, this%count
931
932 if ( this%get(i) .strapprox. substr ) count = count + 1
933
934 enddo
935
936 endif
937
939
940!--------------------------------------------------------------------------------------------------
941
942 function return_subset_of_partial_matches_fn( this, substr ) result(new_fstring)
943
944 class(fstring_list_t), intent(inout) :: this
945 character (len=*), intent(in) :: substr
946 type (fstring_list_t) :: new_fstring
947
948 ! [ LOCALS ]
949 integer (c_int) :: i
950 character (len=:), allocatable :: temp_str
951
952 do i=1, this%count
953 temp_str = this%get(i)
954 if ( temp_str .containssimilar. substr ) call new_fstring%append(temp_str)
955 enddo
956
957 if ( new_fstring%count == 0 ) new_fstring = "<NA>"
958
960
961!--------------------------------------------------------------------------------------------------
962
963 function return_indices_of_matching_list_entries_fn(this, character_str) result(index_values)
964
965 class(fstring_list_t), intent(inout) :: this
966 character (len=*), intent(in) :: character_str
967 integer (c_int), allocatable :: index_values(:)
968
969 ! [ LOCALS ]
970 integer (c_int) :: i
971 integer (c_int) :: match_index
972 logical (c_bool) :: string_present( this%count )
973 integer (c_int) :: number_of_matches
974
975 string_present = .false._c_bool
976 match_index = 0
977
978 do i=1, this%count
979 if ( this%get(i) .strapprox. character_str ) string_present(i) = .true._c_bool
980 enddo
981
982 number_of_matches = count(string_present)
983 if (number_of_matches > 0 ) then
984 allocate( index_values(number_of_matches) )
985 do i=1, this%count
986 if (string_present(i)) then
987 match_index = match_index + 1
988 index_values(match_index) = i
989 endif
990 enddo
991 else
992 allocate( index_values(1) )
993 index_values(1) = -9999
994 endif
995
997
998!--------------------------------------------------------------------------------------------------
999
1000 function return_list_of_unique_values_fn(this) result(new_fstring)
1001
1002 class(fstring_list_t), intent(inout) :: this
1003 type (fstring_list_t) :: new_fstring
1004
1005 integer (c_int) :: i
1006 character (len=:), allocatable :: temp_str
1007
1008 do i=1, this%count
1009
1010 temp_str = this%get(i)
1011 if ( new_fstring%count_matching( temp_str ) == 0 ) call new_fstring%append(temp_str)
1012
1013 enddo
1014
1015 if ( new_fstring%count == 0 ) new_fstring = "<NA>"
1016
1018
1019!--------------------------------------------------------------------------------------------------
1020
1021 subroutine print_as_markdown_sub(this, lu)
1022
1023 use iso_fortran_env, only : output_unit
1024
1025 class(fstring_list_t), intent(inout) :: this
1026 integer (c_int), optional :: lu
1027
1028 ! [ LOCALS ]
1029 integer (c_int) :: lu_
1030 integer (c_int) :: i
1031
1032 if (present(lu) ) then
1033 lu_ = lu
1034 else
1035 lu_ = output_unit
1036 endif
1037
1038 write(lu_, fmt="('|',a,t21,'|',a,t72,'|')") "Index","Value"
1039 write(lu_, fmt="('|',a,t21,'|',a,t72,'|')") repeat("-",18)//":", repeat("-",49)//":"
1040
1041 do i=1, this%count
1042
1043 write(lu_, fmt="('|',i10,t21,'|',a,t72,'|')") i, this%get(i)
1044
1045 enddo
1046
1047 end subroutine print_as_markdown_sub
1048
1049end module fstring_list
integer(c_int), parameter, private na_int
Definition fstring.F90:177
real(c_double), parameter, private na_double
Definition fstring.F90:179
real(c_float), parameter, private na_float
Definition fstring.F90:178
logical(c_bool) function, dimension(:), allocatable retrieve_values_as_logical_fn(this)
subroutine append_character_array_to_fstring_sub(this, character_str)
real(c_float) function, dimension(:), allocatable retrieve_values_as_float_fn(this)
subroutine quicksort_int_sub(this, sort_order)
character(len=:) function, allocatable retrieve_values_for_range_of_indices_fn(this, start_indx, end_indx)
subroutine append_character_to_fstring_sub(this, character_str)
subroutine append_fstring_to_fstring_sub(this, other_fstring)
type(fstring_list_t) function return_subset_of_partial_matches_fn(this, substr)
pure integer(c_int) function return_count_of_matching_strings_fn(this, substr, match_case)
logical(c_bool) function are_there_missing_list_values_fn(this)
integer(c_int) function, dimension(:), allocatable return_indices_of_matching_list_entries_fn(this, character_str)
subroutine assign_fstring_to_character_sub(character_str, string_list)
subroutine print_as_markdown_sub(this, lu)
integer(c_int) function, dimension(:), allocatable retrieve_values_as_integer_fn(this)
pure character(len=:) function, allocatable retrieve_value_from_list_at_index_fn(this, index_val)
subroutine quicksort_float_sub(this, sort_order)
subroutine assign_character_to_fstring_sub(this, character_str)
character(len=:) function, allocatable list_all_fn(this, delimiter_chr)
subroutine clear_list_sub(this)
real(c_double) function, dimension(:), allocatable retrieve_values_as_double_fn(this)
recursive subroutine qsort_alpha(sort_group, nrec)
recursive subroutine qsort_float(sort_group, nrec)
integer(c_int) function count_strings_in_list_fn(this)
subroutine replace_value_at_index_sub(this, index_val, character_str)
subroutine print_all_entries_sub(this)
subroutine quicksort_alpha_sub(this, sort_order)
type(fstring_list_t) function split_character_into_fstring_list_fn(character_str, delimiter_chr)
type(fstring_list_t) function return_list_of_unique_values_fn(this)
recursive subroutine qsort_int(sort_group, nrec)