@@ -21,40 +21,19 @@ module sort_generic_extras
2121
2222contains
2323
24- elemental function fortranstring_less (self , other ) &
24+ ! Lexicographically compare strings of equal length.
25+ elemental function chars_less (left , right , length ) &
2526 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
2830 logical :: fresult
2931 integer :: i, lchar, rchar
3032
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-
5433 ! 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))
5837 if (lchar < rchar) then
5938 fresult = .true.
6039 return
@@ -64,11 +43,35 @@ elemental function fortranstring_less(self, other) &
6443 endif
6544 end do
6645
67- ! Everything is equal: therefore not strictly "less than"
6846 fresult = .false.
6947end function
7048
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+
7173! C++-accessible comparison function for two pointers-to-strings
74+ ! (null strings always compare "greater than" to move to end of a list)
7275function compare_strings (lcptr , rcptr ) bind(C) &
7376 result(fresult)
7477 use , intrinsic :: ISO_C_BINDING
@@ -78,20 +81,20 @@ function compare_strings(lcptr, rcptr) bind(C) &
7881 type (FortranString), pointer :: lptr
7982 type (FortranString), pointer :: rptr
8083
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
8291 ! Both associated: convert from C to Fortran pointers
8392 call c_f_pointer(cptr= lcptr, fptr= lptr)
8493 call c_f_pointer(cptr= rcptr, fptr= rptr)
8594
8695 ! Compare the strings
8796 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.
9397 endif
94-
9598end function
9699end module
97100
@@ -139,11 +142,11 @@ program sort_generic_example
139142 ! Print the results
140143 write (STDOUT, * ) " Sorted:"
141144 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
146148 endif
149+ write (STDOUT, " (i3, ': ', a)" ) i, fs_array(i)% chars
147150 enddo
148151
149152end program
0 commit comments