module ListClass use iso_fortran_env implicit none !> String-like data content. This is not used for compatibility. type :: List_content_ !> String-like data content. This is not used for compatibility. character(:), allocatable :: char end type type :: List_fix_content_ !> This is a data content. Please change the word limit of 200 if you need. character(len=200) :: char !> Effective character length: if "hello" in char, the char_len should be 5. integer(int32) :: char_len end type !> This is a derived type of list, where we can create a list instance and do some basic operations such as GET, APPEND, SPLIT. type :: List_ !> This attribute is no used. type(List_content_), allocatable :: content(:) !> This attribute is active. All entities in a list are contained in this list. type(List_fix_content_), allocatable :: fcontent(:) !> A list instance can have an array of list. type(List_), allocatable :: list(:) contains procedure, public :: get => get_list_content_listclass !! GET operation for a list instance. procedure, public :: append => append_list_content_listclass !! APPEND operation for a list instance. procedure, public :: new => new_list_listclass !! Initialize and allocate list by a number of content. procedure, public :: print => print_listclass !! It shows the all content in the terminal. procedure, public :: size => size_listclass !! It returns a number of entities of list. procedure, public :: help => help_listclass !! It shows the help of the listclass. procedure, public :: split => split_char_into_list !! It sets entities by splitting a string by a delimiter. end type interface to_list !! It converts various lists or data structures into a list. module procedure to_list_repeat_listclass, to_list_0_listclass, to_list_1_listclass, & to_list_2_listclass, to_list_3_listclass, to_list_4_listclass, & to_list_5_listclass, to_list_6_listclass, to_list_7_listclass, & to_list_int32vec_listclass, & to_list_real32vec_listclass, & to_list_real64vec_listclass end interface interface operator(//) !! This merges two lists into a list. module procedure joint_listclass end interface interface operator(//) !! This merges two contents of a list into a list. module procedure joint_listcontentclass, joint_arraylistcontentclass end interface interface operator(.get.) !! This is a GET operator for a list. module procedure get_element_of_listclass end interface interface argv !! This returns a list of the command line arguments. module procedure argv_get_cmd_args_as_list end interface interface str !! This converts list to a string (an allocatable array of character.) module procedure str_listclass end interface contains ! ##################################################### function argv_get_cmd_args_as_list() result(ret) type(List_) :: ret integer(int32) ::i, n, length, status character(:),allocatable :: this_arg !character(:),allocatable ::line n = command_argument_count() call ret%new(n) do i = 1,n call get_command_argument(i,length=length,status=status) if(allocated(this_arg))then deallocate(this_arg) endif allocate(character(length)::this_arg) call get_command_argument(i,this_arg,status=status) ret%fcontent(i)%char = this_arg ret%fcontent(i)%char_len = length enddo end function ! ##################################################### pure function get_list_content_listclass(this, idx) result(ret) class(List_), intent(in) :: this integeR(int32), intent(in) :: idx character(:), allocatable :: ret if (allocated(this%fcontent))then ret = this%fcontent(idx)%char(1:this%fcontent(idx)%char_len) return endif if (.not. allocated(this%fcontent)) then ret = "" return end if end function ! ##################################################### pure subroutine new_list_listclass(this, length) class(List_), intent(inout) :: this integer(int32), intent(in) :: length integer(int32) :: i !if (allocated(this%fcontent)) then ! deallocate (this%fcontent) !end if if (allocated(this%fcontent)) then deallocate (this%fcontent) end if allocate (this%fcontent(length)) do i = 1, length this%fcontent(i)%char = "" end do end subroutine ! ##################################################### subroutine append_list_content_listclass(this, char) class(List_), intent(inout) :: this character(*), intent(in) :: char type(List_) :: buf integer(int32) :: i, n buf = this n = size(buf%fcontent) call this%new(length=size(buf%fcontent) + 1) do i = 1, size(buf%fcontent) this%fcontent(i)%char = buf%fcontent(i)%char this%fcontent(i)%char_len = buf%fcontent(i)%char_len end do this%fcontent(n + 1)%char = char this%fcontent(n + 1)%char_len = len(char) end subroutine ! ##################################################### ! ##################################################### pure function size_listclass(this) result(ret) class(List_), intent(in) :: this integer(int32) :: ret ret = size(this%fcontent) end function ! ##################################################### ! ##################################################### subroutine print_listclass(this) class(List_), intent(in) :: this character(1) :: comma integer(int32) :: i print *, str(this) end subroutine ! ##################################################### ! ##################################################### function str_listclass(this) result(ret) class(List_), intent(in) :: this character(1) :: comma character(:),allocatable :: ret integer(int32) :: i ret = "" ret = ret // "[" if(allocated(this%fcontent))then do i = 1, this%size() if (i < this%size())then ret = ret // trim(this%fcontent(i)%char(1:this%fcontent(i)%char_len)) // "," else ret = ret // trim(this%fcontent(i)%char(1:this%fcontent(i)%char_len)) endif end do endif ret = ret // "]" end function ! ##################################################### pure function joint_listcontentclass(List_content_1, List_content_2) result(List_content) type(List_fix_content_), intent(in) :: List_content_1, List_content_2 type(List_fix_content_) :: List_content List_content%char = List_content_1%char//List_content_2%char end function ! ##################################################### pure function joint_listclass(list1, list2) result(ret_list) type(List_), intent(in) :: list1, list2 type(List_) :: ret_list integer(int32) :: i if (allocated(list1%fcontent) .and. .not. allocated(list2%fcontent)) then ret_list = list1 return end if if (allocated(list2%fcontent) .and. .not. allocated(list1%fcontent)) then ret_list = list2 return end if if (.not. allocated(list1%fcontent) .and. .not. allocated(list2%fcontent)) then return end if call ret_list%new(list1%size() + list2%size()) do i = 1, list1%size() ret_list%fcontent(i)%char = list1%fcontent(i)%char ret_list%fcontent(i)%char_len = list1%fcontent(i)%char_len end do do i = 1, list2%size() ret_list%fcontent(i + list1%size())%char = list2%fcontent(i)%char ret_list%fcontent(i + list1%size())%char_len = list2%fcontent(i)%char_len end do end function pure function joint_arraylistcontentclass(List_content_1, List_content_2) result(List_content) type(List_fix_content_), intent(in) :: List_content_1(:), List_content_2(:) type(List_fix_content_), allocatable :: List_content(:) integer(int32) :: i List_content = List_content_1 do i = 1, size(List_content_1) List_content(i)%char(1:List_content(i)%char_len) = List_content(i)%char(1:List_content(i)%char_len)& //List_content_2(i)%char(1:List_content_2(i)%char_len) end do end function ! ##################################################### function to_list_0_listclass() result(this) type(List_) :: this allocate (this%fcontent(0)) end function ! ##################################################### function to_list_repeat_listclass(char1, num_repeat) result(this) !! It creates a list with a same entity as char1 into a list. character(*), intent(in) :: char1 !! This entity will be repeated for all contents in a returned list. type(List_) :: this integer(int32), intent(in) :: num_repeat !! Number of the repeat. integer(int32) :: i allocate (this%fcontent(num_repeat)) do i = 1, num_repeat this%fcontent(i)%char = char1 this%fcontent(i)%char_len = len(char1) end do end function ! ##################################################### ! ##################################################### function to_list_1_listclass(char1) result(this) !! Create a list with a length of 1, where the entity char1 is the content. character(*), intent(in) :: char1 !! The entity char1 is the content. character(:), allocatable :: buf type(List_) :: this integer(int32) :: ac_from, ac_to ac_from = index(char1, "[") ac_to = index(char1, "]", back=.true.) if (ac_from /= 0 .and. ac_to /= 0) then buf = char1(ac_from + 1:ac_to - 1) call this%split(buf, ",") else allocate (this%fcontent(1)) this%fcontent(1)%char = char1 this%fcontent(1)%char_len = len(char1) end if end function ! ##################################################### function to_list_2_listclass(char1, char2) result(this) character(*), intent(in) :: char1, char2 type(List_) :: this allocate (this%fcontent(2)) this%fcontent(1)%char = char1 this%fcontent(2)%char = char2 this%fcontent(1)%char_len = len(char1) this%fcontent(2)%char_len = len(char2) end function ! ##################################################### function to_list_3_listclass(char1, char2, char3) result(this) character(*), intent(in) :: char1, char2, char3 type(List_) :: this allocate (this%fcontent(3)) this%fcontent(1)%char = char1 this%fcontent(2)%char = char2 this%fcontent(3)%char = char3 this%fcontent(1)%char_len = len(char1) this%fcontent(2)%char_len = len(char2) this%fcontent(3)%char_len = len(char3) end function ! ##################################################### function to_list_4_listclass(char1, char2, char3, char4) result(this) character(*), intent(in) :: char1, char2, char3, char4 type(List_) :: this allocate (this%fcontent(4)) this%fcontent(1)%char = char1 this%fcontent(2)%char = char2 this%fcontent(3)%char = char3 this%fcontent(4)%char = char4 this%fcontent(1)%char_len = len(char1) this%fcontent(2)%char_len = len(char2) this%fcontent(3)%char_len = len(char3) this%fcontent(4)%char_len = len(char4) end function ! ##################################################### ! ##################################################### function to_list_5_listclass(char1, char2, char3, char4, char5) result(this) character(*), intent(in) :: char1, char2, char3, char4, char5 type(List_) :: this allocate (this%fcontent(5)) this%fcontent(1)%char = char1 this%fcontent(2)%char = char2 this%fcontent(3)%char = char3 this%fcontent(4)%char = char4 this%fcontent(5)%char = char5 this%fcontent(1)%char_len = len(char1) this%fcontent(2)%char_len = len(char2) this%fcontent(3)%char_len = len(char3) this%fcontent(4)%char_len = len(char4) this%fcontent(5)%char_len = len(char5) end function ! ##################################################### ! ##################################################### function to_list_6_listclass(char1, char2, char3, char4, char5, char6) result(this) character(*), intent(in) :: char1, char2, char3, char4, char5, char6 type(List_) :: this allocate (this%fcontent(6)) this%fcontent(1)%char = char1 this%fcontent(2)%char = char2 this%fcontent(3)%char = char3 this%fcontent(4)%char = char4 this%fcontent(5)%char = char5 this%fcontent(6)%char = char6 this%fcontent(1)%char_len = len(char1) this%fcontent(2)%char_len = len(char2) this%fcontent(3)%char_len = len(char3) this%fcontent(4)%char_len = len(char4) this%fcontent(5)%char_len = len(char5) this%fcontent(6)%char_len = len(char6) end function ! ##################################################### ! ##################################################### function to_list_7_listclass(char1, char2, char3, char4, char5, char6, char7) result(this) character(*), intent(in) :: char1, char2, char3, char4, char5, char6, char7 type(List_) :: this allocate (this%fcontent(7)) this%fcontent(1)%char = char1 this%fcontent(2)%char = char2 this%fcontent(3)%char = char3 this%fcontent(4)%char = char4 this%fcontent(5)%char = char5 this%fcontent(6)%char = char6 this%fcontent(7)%char = char7 this%fcontent(1)%char_len = len(char1) this%fcontent(2)%char_len = len(char2) this%fcontent(3)%char_len = len(char3) this%fcontent(4)%char_len = len(char4) this%fcontent(5)%char_len = len(char5) this%fcontent(6)%char_len = len(char6) this%fcontent(7)%char_len = len(char7) end function ! ##################################################### ! ##################################################### function to_list_int32vec_listclass(int32vec) result(this) integer(int32), intent(in) :: int32vec(:) type(List_) :: this integer(int32) :: i character(len=50):: b allocate (this%fcontent(size(int32vec))) do i = 1, size(int32vec) write (b, *) int32vec(i) this%fcontent(i)%char = trim(adjustl(b)) this%fcontent(i)%char_len = len(this%fcontent(i)%char) end do end function ! ##################################################### ! ##################################################### function to_list_real32vec_listclass(real32vec) result(this) real(real32), intent(in) :: real32vec(:) type(List_) :: this integer(int32) :: i character(len=50):: b allocate (this%fcontent(size(real32vec))) do i = 1, size(real32vec) write (b, '(f0.10)') real32vec(i) this%fcontent(i)%char = trim(adjustl(b)) this%fcontent(i)%char_len = len(this%fcontent(i)%char) end do end function ! ##################################################### ! ##################################################### function to_list_real64vec_listclass(real64vec) result(this) real(real64), intent(in) :: real64vec(:) type(List_) :: this integer(int32) :: i character(len=50):: b allocate (this%fcontent(size(real64vec))) do i = 1, size(real64vec) write (b, '(G31.20)') real64vec(i) this%fcontent(i)%char = trim(adjustl(b)) this%fcontent(i)%char_len = len(this%fcontent(i)%char) end do end function ! ##################################################### ! ##################################################### subroutine help_listclass(this) class(List_), intent(in) :: this print *, "function get(this,idx) " print *, "subroutine append(this,char) " print *, "subroutine new(this,length)" print *, "print => print_listclass" print *, "size => size_listclass" end subroutine ! ##################################################### ! ##################################################### subroutine split_char_into_list(this, str_val, delimiter) character(*), intent(in) :: str_val, delimiter class(List_), intent(inout) :: this integer(int32) :: i, n, last_idx, current_idx ! split charactor(*) into list ! First, count the number of entity n = 0 do i = 1, len(str_val) if (str_val(i:i) == delimiter) then n = n + 1 end if end do call this%new(n) last_idx = 1 n = 0 do current_idx = 1, len(str_val) - (len(delimiter) - 1) if (str_val(current_idx:current_idx + len(delimiter) - 1) == delimiter) then n = n + 1 this%fcontent(n)%char = trim(str_val(last_idx:current_idx - 1)) this%fcontent(n)%char_len = (current_idx - 1)-last_idx+1 last_idx = current_idx + 1 end if end do if (index(str_val, delimiter, back=.true.) < len(str_val)) then n = index(str_val, delimiter, back=.true.) if (trim(str_val(n + 1:)) /= "") then call this%append(str_val(n + 1:)) end if end if end subroutine ! ##################################################### function get_element_of_listclass(this_list,idx) result(ret) character(:),allocatable :: ret type(List_),intent(in) :: this_list integer(int32),intent(in) :: idx ret = "" if(allocated(this_list%fcontent) )then if (size(this_list%fcontent) >= idx )then ret = this_list%fcontent(idx)%char(1:this_list%fcontent(idx)%char_len) endif endif end function end module ListClass