64 implicit none;
private
70 operator(.contains.), &
113 character(:),
allocatable :: chars
116 procedure, pass(lhs),
private :: character_assign_string
117 procedure, pass(rhs),
private :: string_assign_character
118 procedure, pass(lhs),
private :: string_eq_string
119 procedure, pass(lhs),
private :: string_eq_character
120 procedure, pass(rhs),
private :: character_eq_string
121 procedure, pass(dtv),
private :: write_formatted
123 generic,
public ::
assignment(=) => character_assign_string, &
124 string_assign_character
125 generic,
public ::
operator(==) => string_eq_string, &
126 string_eq_character, &
128 generic,
public ::
write(formatted) => write_formatted
165 module procedure :: string_len
202 module procedure :: string_len_trim
241 module procedure :: string_trim
265 interface operator(//)
266 module procedure :: string_concat_string
267 module procedure :: string_concat_character
268 module procedure :: character_concat_string
323 interface operator(.contains.)
324 module procedure :: strings_contain_string
325 module procedure :: strings_contain_character
326 module procedure :: characters_contain_string
327 module procedure :: characters_contain_character
396 module procedure :: index_string_string
397 module procedure :: index_string_character
398 module procedure :: index_character_string
415 subroutine character_assign_string(lhs, rhs)
416 class(string),
intent(inout) :: lhs
417 character(*),
intent(in) :: rhs
419 if (
allocated(lhs%chars))
deallocate(lhs%chars)
420 allocate(lhs%chars, source=rhs)
438 subroutine string_assign_character(lhs, rhs)
439 character(:),
allocatable,
intent(inout) :: lhs
440 class(string),
intent(in) :: rhs
460 elemental integer function string_len(this)
result(res)
461 class(
string),
intent(in) :: this
463 if (
allocated(this%chars))
then
464 res =
len(this%chars)
485 pure integer function string_len_trim(this)
result(res)
486 class(
string),
intent(in) :: this
488 if (
allocated(this%chars))
then
500 pure function string_trim(this)
result(res)
501 class(
string),
intent(in) :: this
502 character(:),
allocatable :: res
504 if (
allocated(this%chars))
then
505 res =
trim(this%chars)
517 pure function string_concat_string(lhs, rhs)
result(res)
518 class(
string),
intent(in) :: lhs
519 class(
string),
intent(in) :: rhs
520 character(:),
allocatable :: res
522 if (
allocated(lhs%chars) .and.
allocated(rhs%chars))
then
523 res = lhs%chars // rhs%chars
524 elseif (
allocated(lhs%chars))
then
526 elseif (
allocated(rhs%chars))
then
539 pure function string_concat_character(lhs, rhs)
result(res)
540 class(
string),
intent(in) :: lhs
541 character(*),
intent(in) :: rhs
542 character(:),
allocatable :: res
544 if (
allocated(lhs%chars))
then
545 res = lhs%chars // rhs
557 pure function character_concat_string(lhs, rhs)
result(res)
558 character(*),
intent(in) :: lhs
559 class(
string),
intent(in) :: rhs
560 character(:),
allocatable :: res
562 if (
allocated(rhs%chars))
then
563 res = lhs // rhs%chars
575 elemental function string_eq_string(lhs, rhs)
result(res)
576 class(
string),
intent(in) :: lhs
577 class(
string),
intent(in) :: rhs
580 if (.not.
allocated(lhs%chars))
then
581 res = .not.
allocated(rhs%chars)
583 res = lhs%chars == rhs%chars
593 elemental function string_eq_character(lhs, rhs)
result(res)
594 class(
string),
intent(in) :: lhs
595 character(*),
intent(in) :: rhs
598 if (.not.
allocated(lhs%chars))
then
601 res = lhs%chars == rhs
611 elemental function character_eq_string(lhs, rhs)
result(res)
612 character(*),
intent(in) :: lhs
613 class(
string),
intent(in) :: rhs
616 if (.not.
allocated(rhs%chars))
then
619 res = rhs%chars == lhs
663 subroutine write_formatted(dtv, unit, iotype, v_list, iostat, iomsg)
664 class(
string),
intent(in) :: dtv
665 integer,
intent(in) :: unit
666 character(*),
intent(in) :: iotype
667 integer,
intent(in) :: v_list(:)
668 integer,
intent(out) :: iostat
669 character(*),
intent(inout) :: iomsg
671 if (
allocated(dtv%chars))
then
672 write(unit,
'(A)', iostat=iostat, iomsg=iomsg) dtv%chars
674 write(unit,
'(A)', iostat=iostat, iomsg=iomsg)
''
715 character(*),
intent(in) :: str
716 character(*),
intent(in) :: arg1
717 integer,
intent(out),
optional :: idx
723 if (
present(idx)) idx = i
731 character function head(str)
result(res)
732 character(*),
intent(in) :: str
745 character function tail(str)
result(res)
746 character(*),
intent(in) :: str
763 character(*),
intent(in) :: str1
764 character(*),
intent(in) :: str2
765 character(:),
allocatable :: res
769 n1 =
len(str1); n2 = 1
770 if (
head(str1) ==
'!')
then
780 if (
head(adjustl(str2(n2:))) ==
'&')
then
781 n2 =
index(str2,
'&') + 1
786 if (
tail(str1(:n1)) ==
'(') n1 =
index(str1(:n1),
'(', back=.true.)
789 if (
len(str1) > 0 .and.
len(str2) >= n2)
then
790 if (str1(n1:n1) ==
' ' .and. str2(n2:n2) ==
' ') n2 = n2 + 1
792 res = str1(:n1) // str2(n2:)
809 character(*),
intent(in) :: str
810 character(len_trim(str)) :: res
812 integer :: ilen, ioffset, iquote, iqc, iav, i
815 ioffset = iachar(
'A') - iachar(
'a')
819 iav = iachar(str(i:i))
820 if (iquote == 0 .and. (iav == 34 .or. iav == 39))
then
825 if (iquote == 1 .and. iav == iqc)
then
829 if (iquote == 1) cycle
830 if (iav >= iachar(
'a') .and. iav <= iachar(
'z'))
then
831 res(i:i) = achar(iav + ioffset)
852 character(*),
intent(in) :: str
853 character(len_trim(str)) :: res
855 integer :: ilen, ioffset, iquote, iqc, iav, i
858 ioffset = iachar(
'A') - iachar(
'a')
862 iav = iachar(str(i:i))
863 if (iquote == 0 .and. (iav == 34 .or. iav == 39))
then
868 if (iquote == 1 .and. iav == iqc)
then
872 if (iquote == 1) cycle
873 if (iav >= iachar(
'A') .and. iav <= iachar(
'Z'))
then
874 res(i:i) = achar(iav - ioffset)
887 integer,
intent(in) :: unit
888 character(*),
intent(in) :: str
893 if (
head(str) /=
'!')
then
899 write(unit,
'(A)') str(n *
chksize + 1:)
908 character(1) function previous(line, pos)
result(res)
909 character(*),
intent(in) :: line
910 integer,
intent(inout) :: pos
914 res =
trim(line(pos:pos))
916 do while (line(pos:pos) ==
' ')
930 logical function strings_contain_string(lhs, rhs)
result(res)
931 type(
string),
intent(in) :: lhs(:)
932 type(
string),
intent(in) :: rhs
938 if (lhs(i) == rhs)
then
951 logical function strings_contain_character(lhs, rhs)
result(res)
952 type(
string),
intent(in) :: lhs(:)
953 character(*),
intent(in) :: rhs
959 if (lhs(i) == rhs)
then
972 logical function characters_contain_character(lhs, rhs)
result(res)
973 character(*),
intent(in) :: lhs(:)
974 character(*),
intent(in) :: rhs
980 if (lhs(i) == rhs)
then
993 logical function characters_contain_string(lhs, rhs)
result(res)
994 character(*),
intent(in) :: lhs(:)
995 type(
string),
intent(in) :: rhs
1001 if (lhs(i) == rhs)
then
1008 integer function index_string_string(str, substr, back)
result(res)
1009 class(
string),
intent(in) :: str
1010 class(
string),
intent(in) :: substr
1011 logical,
intent(in),
optional :: back
1013 res =
index(str%chars, substr%chars, back=back)
1016 integer function index_character_string(str, substr, back)
result(res)
1017 character(*),
intent(in) :: str
1018 class(
string),
intent(in) :: substr
1019 logical,
intent(in),
optional :: back
1021 res =
index(str, substr%chars, back=back)
1024 integer function index_string_character(str, substr, back)
result(res)
1025 class(
string),
intent(in) :: str
1026 character(*),
intent(in) :: substr
1027 logical,
intent(in),
optional :: back
1029 res =
index(str%chars, substr, back=back)
integer, parameter, public chksize
Default chunk size used for internal buffering operations.
character function, public tail(str)
Returns the last non-blank character of a string.
pure character(len_trim(str)) function, public lowercase(str)
Convert string to lower case (respects contents of quotes).
subroutine, public writechk(unit, str)
Write a long line split into chunks of size CHKSIZE with continuation (&).
character(1) function, public previous(line, pos)
Returns the previous non-blank character before position pos (updates pos).
pure character(len_trim(str)) function, public uppercase(str)
Convert string to upper case (respects contents of quotes).
character(:) function, allocatable, public concat(str1, str2)
Smart concatenation that removes continuation markers (&) and handles line-continuation rules.
logical function, public starts_with(str, arg1, idx)
Checks if a string starts with a given prefix Returns .true. if the string str (after trimming leadin...
character function, public head(str)
Returns the first character of the trimmed string.
Locate the position of a substring.
Return the trimmed length of a string object.
Return the length of a string object.
Remove trailing blanks from a string object.
Represents text as a sequence of ASCII code units. The derived type wraps an allocatable character ar...