parse_stream_name Function

private pure function parse_stream_name(stream_name) result(var_info_list)

Parse a stream name, which consists of one or more stream name fragments, and return the corresponding variable information as a list of var_info_type. Multiple stream name fragments should be separated by "+" (i.e., a plus, meaning "addition" operation) or "-" (i.e., a minus, meaning "subtraction" operation). A stream name fragment can be a predefined stream name (e.g., "invariant", "input", etc.) or a single variable name. For example, a stream name of "invariant+input+restart" means the union of variables in the "invariant", "input", and "restart" streams. Duplicate variable information in the resulting list is discarded. (KCW, 2024-06-01)

Arguments

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

Return Value type(var_info_type), allocatable, (:)


Calls

proc~~parse_stream_name~~CallsGraph proc~parse_stream_name parse_stream_name proc~index_unique index_unique proc~parse_stream_name->proc~index_unique proc~parse_stream_name_fragment parse_stream_name_fragment proc~parse_stream_name->proc~parse_stream_name_fragment

Called by

proc~~parse_stream_name~~CalledByGraph proc~parse_stream_name parse_stream_name proc~dyn_mpas_init_stream_with_pool mpas_dynamical_core_type%dyn_mpas_init_stream_with_pool proc~dyn_mpas_init_stream_with_pool->proc~parse_stream_name proc~dyn_mpas_read_write_stream mpas_dynamical_core_type%dyn_mpas_read_write_stream proc~dyn_mpas_read_write_stream->proc~parse_stream_name proc~dyn_mpas_read_write_stream->proc~dyn_mpas_init_stream_with_pool proc~dyn_init dyn_init proc~dyn_init->proc~dyn_mpas_read_write_stream proc~dyn_variable_dump dyn_variable_dump proc~dyn_variable_dump->proc~dyn_mpas_read_write_stream proc~model_grid_init model_grid_init proc~model_grid_init->proc~dyn_mpas_read_write_stream proc~dyn_final dyn_final proc~dyn_final->proc~dyn_variable_dump proc~stepon_final stepon_final proc~stepon_final->proc~dyn_final

Variables

Type Visibility Attributes Name Initial
integer, private :: i
integer, private :: j
integer, private :: n
integer, private :: offset
character(len=:), private, allocatable :: stream_name_fragment
character(len=1), private :: stream_name_operator
character(len=*), private, parameter :: supported_stream_name_operator = '+-'
type(var_info_type), private, allocatable :: var_info_list_buffer(:)
character(len=len(invariant_var_info_list%name)), private, allocatable :: var_name_list(:)

Source Code

    pure function parse_stream_name(stream_name) result(var_info_list)
        character(*), intent(in) :: stream_name
        type(var_info_type), allocatable :: var_info_list(:)

        character(*), parameter :: supported_stream_name_operator = '+-'
        character(1) :: stream_name_operator
        character(:), allocatable :: stream_name_fragment
        character(len(invariant_var_info_list % name)), allocatable :: var_name_list(:)
        integer :: i, j, n, offset
        type(var_info_type), allocatable :: var_info_list_buffer(:)

        n = len_trim(stream_name)

        if (n == 0) then
            ! Empty character string means empty list.
            var_info_list = parse_stream_name_fragment('')

            return
        end if

        i = scan(stream_name, supported_stream_name_operator)

        if (i == 0) then
            ! No operators are present in the stream name. It is just a single stream name fragment.
            stream_name_fragment = stream_name
            var_info_list = parse_stream_name_fragment(stream_name_fragment)

            return
        end if

        offset = 0
        var_info_list = parse_stream_name_fragment('')

        do while (.true.)
            ! Extract operator from the stream name.
            if (offset > 0) then
                stream_name_operator = stream_name(offset:offset)
            else
                stream_name_operator = '+'
            end if

            ! Extract stream name fragment from the stream name.
            if (i > 1) then
                stream_name_fragment = stream_name(offset + 1:offset + i - 1)
            else
                stream_name_fragment = ''
            end if

            ! Process the stream name fragment according to the operator.
            if (len_trim(stream_name_fragment) > 0) then
                var_info_list_buffer = parse_stream_name_fragment(stream_name_fragment)

                select case (stream_name_operator)
                    case ('+')
                        var_info_list = [var_info_list, var_info_list_buffer]
                    case ('-')
                        do j = 1, size(var_info_list_buffer)
                            var_name_list = var_info_list % name
                            var_info_list = pack(var_info_list, var_name_list /= var_info_list_buffer(j) % name)
                        end do
                    case default
                        ! Do nothing for unknown operators. Should not happen at all.
                end select
            end if

            offset = offset + i

            ! Terminate loop when everything in the stream name has been processed.
            if (offset + 1 > n) then
                exit
            end if

            i = scan(stream_name(offset + 1:), supported_stream_name_operator)

            ! Run the loop one last time for the remaining stream name fragment.
            if (i == 0) then
                i = n - offset + 1
            end if
        end do

        ! Discard duplicate variable information by names.
        var_name_list = var_info_list % name
        var_info_list = var_info_list(index_unique(var_name_list))
    end function parse_stream_name