split Subroutine

private pure subroutine split(self, tokens, sep, max_tokens)

Arguments

TypeIntentOptionalAttributesName
class(string), intent(in) :: self
type(string), intent(out), allocatable:: tokens(:)
character(kind=CK,len=*), intent(in), optional :: sep
integer, intent(in), optional :: max_tokens

Contents

Source Code


Source Code

   pure subroutine split(self, tokens, sep, max_tokens)
   !< Return a list of substring in the string, using sep as the delimiter string.
   !<
   !< @note Multiple subsequent separators are collapsed to one occurrence.
   !<
   !< @note If `max_tokens` is passed the returned number of tokens is either `max_tokens` or `max_tokens + 1`.
   !<
   !<```fortran
   !< type(string)              :: astring
   !< type(string), allocatable :: strings(:)
   !< logical                   :: test_passed(11)
   !< astring = '+ab-++cre-++cre-ab+'
   !< call astring%split(tokens=strings, sep='+')
   !< test_passed(1) = (strings(1)//''=='ab-'.and.strings(2)//''=='cre-'.and.strings(3)//''=='cre-ab')
   !< astring = 'ab-++cre-++cre-ab+'
   !< call astring%split(tokens=strings, sep='+')
   !< test_passed(2) = (strings(1)//''=='ab-'.and.strings(2)//''=='cre-'.and.strings(3)//''=='cre-ab')
   !< astring = 'ab-++cre-++cre-ab'
   !< call astring%split(tokens=strings, sep='+')
   !< test_passed(3) = (strings(1)//''=='ab-'.and.strings(2)//''=='cre-'.and.strings(3)//''=='cre-ab')
   !< astring = 'Hello '//new_line('a')//'World!'
   !< call astring%split(tokens=strings, sep=new_line('a'))
   !< test_passed(4) = (strings(1)//''=='Hello '.and.strings(2)//''=='World!')
   !< astring = 'Hello World!'
   !< call astring%split(tokens=strings)
   !< test_passed(5) = (strings(1)//''=='Hello'.and.strings(2)//''=='World!')
   !< astring = '+ab-'
   !< call astring%split(tokens=strings, sep='+')
   !< test_passed(6) = (strings(1)//''=='ab-')
   !< astring = '+ab-'
   !< call astring%split(tokens=strings, sep='-')
   !< test_passed(7) = (strings(1)//''=='+ab')
   !< astring = '+ab-+cd-'
   !< call astring%split(tokens=strings, sep='+')
   !< test_passed(8) = (strings(1)//''=='ab-'.and.strings(2)//''=='cd-')
   !< astring = 'ab-+cd-+'
   !< call astring%split(tokens=strings, sep='+')
   !< test_passed(9) = (strings(1)//''=='ab-'.and.strings(2)//''=='cd-')
   !< astring = '+ab-+cd-+'
   !< call astring%split(tokens=strings, sep='+')
   !< test_passed(10) = (strings(1)//''=='ab-'.and.strings(2)//''=='cd-')
   !< astring = '1-2-3-4-5-6-7-8'
   !< call astring%split(tokens=strings, sep='-', max_tokens=3)
   !< test_passed(11) = (strings(1)//''=='1'.and.strings(2)//''=='2'.and.strings(3)//''=='3'.and.strings(4)//''=='4-5-6-7-8')
   !< print '(L1)', all(test_passed)
   !<```
   !=> T <<<
   class(string),             intent(in)           :: self           !< The string.
   type(string), allocatable, intent(out)          :: tokens(:)      !< Tokens substring.
   character(kind=CK, len=*), intent(in), optional :: sep            !< Separator.
   integer,                   intent(in), optional :: max_tokens     !< Fix the maximum number of returned tokens.
   character(kind=CK, len=:), allocatable          :: sep_           !< Separator, default value.
   integer                                         :: No             !< Number of occurrences of sep.
   integer                                         :: t              !< Character counter.
   type(string)                                    :: temporary      !< Temporary storage.
   type(string), allocatable                       :: temp_toks(:,:) !< Temporary tokens substring.

   if (allocated(self%raw)) then
     sep_ = SPACE ; if (present(sep)) sep_ = sep

     temporary = self%unique(sep_)
     No = temporary%count(sep_)

     if (No>0) then
       if (present(max_tokens)) then
         if (max_tokens < No.and.max_tokens > 0) No = max_tokens
       endif
       allocate(temp_toks(3, No))
       temp_toks(:, 1) = temporary%partition(sep_)
       if (No>1) then
         do t=2, No
           temp_toks(:, t) = temp_toks(3, t-1)%partition(sep_)
         enddo
       endif

       if (temp_toks(1, 1)%raw/=''.and.temp_toks(3, No)%raw/='') then
         allocate(tokens(No+1))
         do t=1, No
           if (t==No) then
             tokens(t  ) = temp_toks(1, t)
             tokens(t+1) = temp_toks(3, t)
           else
             tokens(t) = temp_toks(1, t)
           endif
         enddo
       elseif (temp_toks(1, 1)%raw/='') then
         allocate(tokens(No))
         do t=1, No
           tokens(t) = temp_toks(1, t)
         enddo
       elseif (temp_toks(3, No)%raw/='') then
         allocate(tokens(No))
         do t=1, No-1
           tokens(t) = temp_toks(1, t+1)
         enddo
         tokens(No) = temp_toks(3, No)
       else
         allocate(tokens(No-1))
         do t=2, No
           tokens(t-1) = temp_toks(1, t)
         enddo
       endif

     else
       allocate(tokens(1))
       tokens(1) = self
     endif
   endif
   endsubroutine split