Skip to content

Commit 6363ca2

Browse files
committed
Change example to move unallocated strings to the end
This also fixes a potential uninitialized variable usage if both C pointers are null (which wouldn't happen in practice)
1 parent 879b3f7 commit 6363ca2

File tree

1 file changed

+44
-41
lines changed

1 file changed

+44
-41
lines changed

example/sort_generic.f90

Lines changed: 44 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -21,40 +21,19 @@ module sort_generic_extras
2121

2222
contains
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.
6947
end 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)
7275
function 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-
9598
end function
9699
end 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

149152
end program

0 commit comments

Comments
 (0)