read_delimited Subroutine

private subroutine read_delimited(dtv, unit, delim, iostat, iomsg)

Arguments

TypeIntentOptionalAttributesName
class(string), intent(out) :: dtv
integer, intent(in) :: unit
character(kind=CK,len=1), intent(in) :: delim
integer, intent(out) :: iostat
character(kind=CK,len=*), intent(inout) :: iomsg

Contents

Source Code


Source Code

   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