@@ -21,40 +21,19 @@ module sort_generic_extras
21
21
22
22
contains
23
23
24
- elemental function fortranstring_less (self , other ) &
24
+ ! Lexicographically compare strings of equal length.
25
+ elemental function chars_less (left , right , length ) &
25
26
result(fresult)
26
- type (FortranString), intent (in ) :: self
27
- type (FortranString), intent (in ) :: other
27
+ character (len=* ), intent (in ) :: left
28
+ character (len=* ), intent (in ) :: right
29
+ integer , intent (in ) :: length
28
30
logical :: fresult
29
31
integer :: i, lchar, rchar
30
32
31
- if (.not. allocated (self% chars) .and. .not. allocated (other% chars)) then
32
- ! Both deallocated, therefore equal
33
- fresult = .false.
34
- return
35
- elseif (.not. allocated (self% chars)) then
36
- ! self deallocated, therefore less
37
- fresult = .true.
38
- return
39
- elseif (.not. allocated (other% chars)) then
40
- ! other deallocated, therefore greater
41
- fresult = .false.
42
- return
43
- endif
44
-
45
- ! If LHS is shorter, it is "less than" the RHS.
46
- if (len (self% chars) < len (other% chars)) then
47
- fresult = .true.
48
- return
49
- elseif (len (self% chars) > len (other% chars)) then
50
- fresult = .false.
51
- return
52
- endif
53
-
54
33
! If any character code is less than the RHS, it is less than.
55
- do i = 1 , len (self % chars)
56
- lchar = ichar (self % chars (i:i))
57
- rchar = ichar (other % chars (i:i))
34
+ do i = 1 , length
35
+ lchar = ichar (left (i:i))
36
+ rchar = ichar (right (i:i))
58
37
if (lchar < rchar) then
59
38
fresult = .true.
60
39
return
@@ -64,11 +43,35 @@ elemental function fortranstring_less(self, other) &
64
43
endif
65
44
end do
66
45
67
- ! Everything is equal: therefore not strictly "less than"
68
46
fresult = .false.
69
47
end function
70
48
49
+ elemental function fortranstring_less (self , other ) &
50
+ result(fresult)
51
+ type (FortranString), intent (in ) :: self
52
+ type (FortranString), intent (in ) :: other
53
+ logical :: fresult
54
+
55
+ if (.not. allocated (other% chars)) then
56
+ ! RHS is null and LHS is not
57
+ fresult = .true.
58
+ elseif (.not. allocated (self% chars)) then
59
+ ! LHS is null => "greater than" (if LHS is string) or equal (if both null)
60
+ fresult = .false.
61
+ elseif (len (self% chars) < len (other% chars)) then
62
+ ! Since LHS is shorter, it is "less than" the RHS.
63
+ fresult = .true.
64
+ elseif (len (self% chars) > len (other% chars)) then
65
+ ! If RHS is shorter
66
+ fresult = .false.
67
+ else
68
+ ! Compare strings of equal length
69
+ fresult = chars_less(self% chars, other% chars, len (self% chars))
70
+ endif
71
+ end function
72
+
71
73
! C++-accessible comparison function for two pointers-to-strings
74
+ ! (null strings always compare "greater than" to move to end of a list)
72
75
function compare_strings (lcptr , rcptr ) bind(C) &
73
76
result(fresult)
74
77
use , intrinsic :: ISO_C_BINDING
@@ -78,20 +81,20 @@ function compare_strings(lcptr, rcptr) bind(C) &
78
81
type (FortranString), pointer :: lptr
79
82
type (FortranString), pointer :: rptr
80
83
81
- if (c_associated(lcptr) .and. c_associated(rcptr)) then
84
+ if (.not. c_associated(rcptr)) then
85
+ ! RHS is null and LHS is not
86
+ fresult = .true.
87
+ elseif (.not. c_associated(lcptr)) then
88
+ ! LHS is null => "greater than" (if LHS is string) or equal (if both null)
89
+ fresult = .false.
90
+ else
82
91
! Both associated: convert from C to Fortran pointers
83
92
call c_f_pointer(cptr= lcptr, fptr= lptr)
84
93
call c_f_pointer(cptr= rcptr, fptr= rptr)
85
94
86
95
! Compare the strings
87
96
fresult = (lptr < rptr)
88
- elseif (.not. c_associated(lcptr)) then
89
- ! LHS is null => "less than"
90
- fresult = .true.
91
- elseif (.not. c_associated(rcptr)) then
92
- fresult = .false.
93
97
endif
94
-
95
98
end function
96
99
end module
97
100
@@ -139,11 +142,11 @@ program sort_generic_example
139
142
! Print the results
140
143
write (STDOUT, * ) " Sorted:"
141
144
do i = 1 , arr_size
142
- if (allocated (fs_array(i)% chars)) then
143
- write (STDOUT, " (i3, ': ', a)" ) i, fs_array(i)% chars
144
- else
145
- write (STDOUT, " (i3, ': ', a)" ) i, " <UNALLOCATED>"
145
+ if (.not. allocated (fs_array(i)% chars)) then
146
+ write (STDOUT, " (i3, '-', i3, a)" ) i, arr_size, " are unallocated"
147
+ exit
146
148
endif
149
+ write (STDOUT, " (i3, ': ', a)" ) i, fs_array(i)% chars
147
150
enddo
148
151
149
152
end program
0 commit comments