read_delimited Subroutine

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

Arguments

Type IntentOptional AttributesName
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.

Description

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.


Variables

TypeVisibility AttributesNameInitial
character(kind=CK,len=1), public :: ch

A character read.

logical, public :: was_delim

Indicates that the last character read was a delimiter.


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.
  !---------------------------------------------------------------------------------------------------------------------------------
  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
  return
  !---------------------------------------------------------------------------------------------------------------------------------
  endsubroutine read_delimited