Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 9 additions & 37 deletions src/stdlib_string_type.f90
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
!>
!> The specification of this module is available [here](../page/specs/stdlib_string_type.html).
module stdlib_string_type
use stdlib_string_type_low_level, only: maybe0, read_unformatted0, &
read_formatted0, new_string_from_chars0, maybe0_len
implicit none
private

Expand Down Expand Up @@ -314,8 +316,7 @@ end function new_string
pure function new_string_from_chars(chars) result(new)
character(len=*), intent(in) :: chars(:)
type(string_type) :: new
allocate(character(len=len(chars)*size(chars)) :: new%raw)
new%raw = transfer(chars, new%raw)
new%raw = new_string_from_chars0(chars)
end function new_string_from_chars


Expand All @@ -340,7 +341,7 @@ elemental function len_string(string) result(length)
type(string_type), intent(in) :: string
integer :: length

length = merge(len(string%raw), 0, allocated(string%raw))
length = len(maybe(string))

end function len_string

Expand All @@ -351,7 +352,7 @@ elemental function len_trim_string(string) result(length)
type(string_type), intent(in) :: string
integer :: length

length = merge(len_trim(string%raw), 0, allocated(string%raw))
length = len_trim(maybe(string))

end function len_trim_string

Expand Down Expand Up @@ -1010,14 +1011,8 @@ subroutine read_unformatted(string, unit, iostat, iomsg)
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(len=*), intent(inout) :: iomsg
integer, parameter :: long = selected_int_kind(18)
integer(long) :: chunk

read(unit, iostat=iostat, iomsg=iomsg) chunk
if (iostat == 0) then
string%raw = repeat(' ', chunk)
read(unit, iostat=iostat, iomsg=iomsg) string%raw
end if
call read_unformatted0(string%raw, unit, iostat, iomsg)

end subroutine read_unformatted

Expand All @@ -1029,30 +1024,11 @@ subroutine read_formatted(string, unit, iotype, v_list, iostat, iomsg)
integer, intent(in) :: v_list(:)
integer, intent(out) :: iostat
character(len=*), intent(inout) :: iomsg
integer, parameter :: buffer_size = 512
character(len=buffer_size) :: buffer
integer :: chunk

call unused_dummy_argument(iotype)
call unused_dummy_argument(v_list)

string%raw = ''
do
read(unit, '(a)', iostat=iostat, iomsg=iomsg, size=chunk, advance='no') &
buffer
if (iostat > 0) exit
string%raw = string%raw // buffer(:chunk)
if (iostat < 0) then
if (is_iostat_eor(iostat)) then
iostat = 0
end if
exit
end if
end do
call read_formatted0(string%raw, unit, iotype, v_list, iostat, iomsg)

end subroutine read_formatted


!> Do nothing but mark an unused dummy argument as such to acknowledge compile
!> time warning like:
!>
Expand All @@ -1068,12 +1044,8 @@ end subroutine unused_dummy_argument
!> Safely return the character sequences represented by the string
elemental function maybe(string) result(maybe_string)
type(string_type), intent(in) :: string
character(len=len(string)) :: maybe_string
if (allocated(string%raw)) then
maybe_string = string%raw
else
maybe_string = ''
end if
character(len=maybe0_len(string%raw)) :: maybe_string
maybe_string = maybe0(string%raw)
end function maybe


Expand Down
78 changes: 78 additions & 0 deletions src/stdlib_string_type_low_level.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
! Low level API for strings. These utilities are used in the high level API
! for the `string_type`.
module stdlib_string_type_low_level
implicit none

contains

pure function new_string_from_chars0(chars) result(new)
character(len=*), intent(in) :: chars(:)
character(len=:), allocatable :: new
allocate(character(len=len(chars)*size(chars)) :: new)
new = transfer(chars, new)
end function

subroutine read_unformatted0(string, unit, iostat, iomsg)
character(len=:), allocatable, intent(inout) :: string
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(len=*), intent(inout) :: iomsg
integer, parameter :: long = selected_int_kind(18)
integer(long) :: chunk
read(unit, iostat=iostat, iomsg=iomsg) chunk
if (iostat == 0) then
string = repeat(' ', chunk)
read(unit, iostat=iostat, iomsg=iomsg) string
end if
end subroutine

subroutine read_formatted0(string, unit, iotype, v_list, iostat, iomsg)
character(len=:), allocatable, intent(inout) :: string
integer, intent(in) :: unit
character(len=*), intent(in) :: iotype
integer, intent(in) :: v_list(:)
integer, intent(out) :: iostat
character(len=*), intent(inout) :: iomsg
integer, parameter :: buffer_size = 512
character(len=buffer_size) :: buffer
integer :: chunk
call unused_dummy_argument(iotype)
call unused_dummy_argument(v_list)
string = ''
do
read(unit, '(a)', iostat=iostat, iomsg=iomsg, size=chunk, advance='no') &
buffer
if (iostat > 0) exit
string = string // buffer(:chunk)
if (iostat < 0) then
if (is_iostat_eor(iostat)) then
iostat = 0
end if
exit
end if
end do
end subroutine

pure integer function maybe0_len(string) result(n)
character(len=:), allocatable, intent(in) :: string
if (allocated(string)) then
n = len(string)
else
n = 0
end if
end function

pure function maybe0(string) result(maybe_string)
character(len=:), allocatable, intent(in) :: string
character(len=maybe0_len(string)) :: maybe_string
if (allocated(string)) then
maybe_string = string
end if
end function

elemental subroutine unused_dummy_argument(dummy)
class(*), intent(in) :: dummy
associate(dummy => dummy); end associate
end subroutine unused_dummy_argument

end module stdlib_string_type_low_level