fortplot_path_operations.f90 Source File


Source Code

module fortplot_path_operations
    !! Path manipulation and normalization utilities
    !! 
    !! This module handles cross-platform path operations including
    !! path mapping, separator normalization, and path parsing.

    use fortplot_os_detection, only: is_windows

    implicit none
    private

    public :: map_unix_to_windows_path
    public :: normalize_path_separators
    public :: get_parent_directory
    public :: parse_path_segments

contains

    function map_unix_to_windows_path(path) result(mapped_path)
        !! Map Unix-style /tmp paths to Windows-compatible paths
        character(len=*), intent(in) :: path
        character(len=:), allocatable :: mapped_path
        character(len=512) :: temp_dir
        integer :: status
        
        if (is_windows()) then
            if (path == "/tmp") then
                ! Use Windows TEMP directory
                call get_environment_variable("TEMP", temp_dir, status=status)
                if (status == 0 .and. len_trim(temp_dir) > 0) then
                    mapped_path = trim(temp_dir)
                else
                    ! Fallback to local tmp directory
                    mapped_path = "tmp"
                end if
            else if (len(path) >= 5 .and. path(1:5) == "/tmp/") then
                ! Map /tmp/filename to TEMP/filename or tmp/filename
                call get_environment_variable("TEMP", temp_dir, status=status)
                if (status == 0 .and. len_trim(temp_dir) > 0) then
                    mapped_path = trim(temp_dir) // "\" // path(6:)
                else
                    ! Fallback to local tmp directory
                    mapped_path = "tmp" // path(5:)
                end if
            else
                mapped_path = path
            end if
        else
            ! On Unix/Linux, keep paths as-is
            mapped_path = path
        end if
    end function map_unix_to_windows_path

    function normalize_path_separators(path, to_windows) result(normalized)
        !! Normalize path separators for the target platform
        character(len=*), intent(in) :: path
        logical, intent(in) :: to_windows
        character(len=:), allocatable :: normalized
        integer :: i
        
        normalized = path
        
        if (to_windows) then
            ! Convert forward slashes to backslashes
            do i = 1, len(normalized)
                if (normalized(i:i) == '/') then
                    normalized(i:i) = '\'
                end if
            end do
        else
            ! Convert backslashes to forward slashes
            do i = 1, len(normalized)
                if (normalized(i:i) == '\') then
                    normalized(i:i) = '/'
                end if
            end do
        end if
    end function normalize_path_separators

    function get_parent_directory(path) result(parent)
        !! Extract parent directory from a path
        character(len=*), intent(in) :: path
        character(len=:), allocatable :: parent
        integer :: last_sep, i
        
        last_sep = 0
        do i = len_trim(path), 1, -1
            if (path(i:i) == '/' .or. path(i:i) == '\') then
                last_sep = i - 1
                exit
            end if
        end do
        
        if (last_sep > 0) then
            parent = path(1:last_sep)
        else
            parent = ""
        end if
    end function get_parent_directory

    subroutine parse_path_segments(path, segments, n_segments)
        !! Parse a path into directory segments
        character(len=*), intent(in) :: path
        character(len=*), intent(out) :: segments(100)
        integer, intent(out) :: n_segments
        integer :: i, start_pos, path_len
        character :: sep
        
        segments = ""
        n_segments = 0
        path_len = len_trim(path)
        if (path_len == 0) return
        
        ! Determine separator
        if (is_windows()) then
            sep = '\'
        else
            sep = '/'
        end if
        
        ! Handle absolute paths
        start_pos = 1
        if (path(1:1) == '/' .or. path(1:1) == '\') then
            n_segments = 1
            segments(1) = path(1:1)
            start_pos = 2
        else if (path_len >= 2 .and. path(2:2) == ':') then
            ! Windows drive letter
            n_segments = 1
            if (path_len >= 3 .and. (path(3:3) == '\' .or. path(3:3) == '/')) then
                segments(1) = path(1:3)
                start_pos = 4
            else
                segments(1) = path(1:2)
                start_pos = 3
            end if
        end if
        
        ! Parse remaining segments
        i = start_pos
        do while (i <= path_len)
            if (path(i:i) == '/' .or. path(i:i) == '\') then
                if (i > start_pos) then
                    n_segments = n_segments + 1
                    segments(n_segments) = path(start_pos:i-1)
                end if
                start_pos = i + 1
            end if
            i = i + 1
        end do
        
        ! Add final segment
        if (start_pos <= path_len) then
            n_segments = n_segments + 1
            segments(n_segments) = path(start_pos:path_len)
        end if
    end subroutine parse_path_segments

end module fortplot_path_operations