parquet_split_name_list Subroutine

public subroutine parquet_split_name_list(text, names)

Splits a scalar string of column names into the packed array every name-taking array form expects. Separators are commas and semicolons, interchangeably; each token is trimmed of surrounding blanks, and an empty token is dropped rather than being an error (so "a,,b" is two names and "" is none).

This is the ONE tokenizer for the whole library. parquet_prefetch_columns' scalar form has accepted this spelling since 1.0.0 and its behaviour is what is reproduced here exactly; parquet_tables' own name- and key-list forms call the same procedure so that two spellings of one operation cannot disagree about punctuation. Public because a sibling module (parquet_tables) needs it and has no other route to it; src/parquet.f90 makes it private again, so it is not part of the use parquet surface.

A SUBROUTINE with an allocatable intent(out) result, never a function returning character(len=:), allocatable -- see CLAUDE.md's project-wide ban on that shape (gfortran PR113797, a thread-unsafe hidden length temporary).

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: text

names separated by commas and/or semicolons.

character(len=:), intent(out), allocatable :: names(:)

one entry per non-empty token.


Source Code

    subroutine parquet_split_name_list(text, names)
        character(len=*), intent(in) :: text !! names separated by commas and/or semicolons.
        character(len=:), allocatable, intent(out) :: names(:) !! one entry per non-empty token.
        character(len=:), allocatable :: tok
        integer :: i, start, ntok, maxlen, idx
        logical :: at_boundary

        ! Pass 1: count non-empty tokens and find the longest, so the packed array's
        ! element length covers every name exactly.
        ntok = 0
        maxlen = 0
        start = 1
        do i = 1, len(text) + 1
            at_boundary = (i > len(text))
            if (.not. at_boundary) at_boundary = (text(i:i) == ',' .or. text(i:i) == ';')
            if (at_boundary) then
                tok = trim(adjustl(text(start:i-1)))
                if (len(tok) > 0) then
                    ntok = ntok + 1
                    maxlen = max(maxlen, len(tok))
                end if
                start = i + 1
            end if
        end do

        ! len=1 rather than len=0 keeps a no-token result well-formed, matching what
        ! %column_names does for a zero-column table.
        allocate(character(len=max(maxlen, 1)) :: names(ntok))
        idx = 0
        start = 1
        do i = 1, len(text) + 1
            at_boundary = (i > len(text))
            if (.not. at_boundary) at_boundary = (text(i:i) == ',' .or. text(i:i) == ';')
            if (at_boundary) then
                tok = trim(adjustl(text(start:i-1)))
                if (len(tok) > 0) then
                    idx = idx + 1
                    names(idx) = tok
                end if
                start = i + 1
            end if
        end do
    end subroutine parquet_split_name_list