subroutine read_delimited(dtv, unit, delim, iostat, iomsg)
!< Read a delimited string from a unit connected for formatted input.
!<
!< If the closing delimiter is followed by end of record, then we return end of record.
!<
!< @note This does not need a doctest, it being tested by [[string::read_formatted]].
class(string), intent(out) :: dtv !< The string.
integer, intent(in) :: unit !< Logical unit.
character(kind=CK, len=1), intent(in) :: delim !< String delimiter.
integer, intent(out) :: iostat !< IO status code.
character(kind=CK, len=*), intent(inout) :: iomsg !< IO status message.
character(kind=CK, len=1) :: ch !< A character read.
logical :: was_delim !< Indicates that the last character read was a delimiter.
was_delim = .false.
dtv%raw = ''
do
read(unit, "(A)", iostat=iostat, iomsg=iomsg) ch
if (is_iostat_eor(iostat)) then
if (was_delim) then
! end of delimited string followed by end of record is end of the string. Pass back the
! end of record condition to the caller
return
else
! end of record without terminating delimiter - move along
cycle
endif
elseif (iostat /= 0) THEN
return
endif
if (ch == delim) then
if (was_delim) then
! doubled delimiter is one delimiter in the value
dtv%raw = dtv%raw // ch
was_delim = .false.
else
! need to test next character to see what is happening
was_delim = .true.
endif
elseif (was_delim) then
! the previous character was actually the delimiter for the end of the string. Put back this character
read(unit, "(TL1)", iostat=iostat, iomsg=iomsg)
return
else
dtv%raw = dtv%raw // ch
endif
enddo
endsubroutine read_delimited