|
2 | 2 | !!
|
3 | 3 | module fpm_filesystem
|
4 | 4 | use,intrinsic :: iso_fortran_env, only : stdin=>input_unit, stdout=>output_unit, stderr=>error_unit
|
| 5 | + use,intrinsic :: iso_c_binding, only: c_new_line |
5 | 6 | use fpm_environment, only: get_os_type, &
|
6 | 7 | OS_UNKNOWN, OS_LINUX, OS_MACOS, OS_WINDOWS, &
|
7 | 8 | OS_CYGWIN, OS_SOLARIS, OS_FREEBSD, OS_OPENBSD
|
8 | 9 | use fpm_environment, only: separator, get_env, os_is_unix
|
9 |
| - use fpm_strings, only: f_string, replace, string_t, split, dilate, str_begins_with_str |
| 10 | + use fpm_strings, only: f_string, replace, string_t, split, split_first_last, dilate, str_begins_with_str |
10 | 11 | use iso_c_binding, only: c_char, c_ptr, c_int, c_null_char, c_associated, c_f_pointer
|
11 | 12 | use fpm_error, only : fpm_stop, error_t, fatal_error
|
12 | 13 | implicit none
|
@@ -50,6 +51,8 @@ end function c_is_dir
|
50 | 51 | end interface
|
51 | 52 | #endif
|
52 | 53 |
|
| 54 | + character(*), parameter :: eol = new_line('a') !! End of line |
| 55 | + |
53 | 56 | contains
|
54 | 57 |
|
55 | 58 | !> Extract filename from path with/without suffix
|
@@ -302,37 +305,71 @@ integer function number_of_rows(s) result(nrows)
|
302 | 305 | end function number_of_rows
|
303 | 306 |
|
304 | 307 | !> read lines into an array of TYPE(STRING_T) variables expanding tabs
|
305 |
| -function read_lines_expanded(fh) result(lines) |
306 |
| - integer, intent(in) :: fh |
| 308 | +function read_lines_expanded(filename) result(lines) |
| 309 | + character(len=*), intent(in) :: filename |
307 | 310 | type(string_t), allocatable :: lines(:)
|
308 | 311 |
|
309 | 312 | integer :: i
|
310 |
| - integer :: iostat |
311 |
| - character(len=:),allocatable :: line_buffer_read |
| 313 | + character(len=:), allocatable :: content |
| 314 | + integer, allocatable :: first(:), last(:) |
| 315 | + |
| 316 | + content = read_text_file(filename) |
| 317 | + if (len(content) == 0) then |
| 318 | + allocate (lines(0)) |
| 319 | + return |
| 320 | + end if |
| 321 | + |
| 322 | + call split_first_last(content, eol, first, last) ! TODO: \r (< macOS X), \n (>=macOS X/Linux/Unix), \r\n (Windows) |
312 | 323 |
|
313 |
| - allocate(lines(number_of_rows(fh))) |
314 |
| - do i = 1, size(lines) |
315 |
| - call getline(fh, line_buffer_read, iostat) |
316 |
| - lines(i)%s = dilate(line_buffer_read) |
| 324 | + ! allocate lines from file content string |
| 325 | + allocate (lines(size(first))) |
| 326 | + do i = 1, size(first) |
| 327 | + allocate(lines(i)%s, source=dilate(content(first(i):last(i)))) |
317 | 328 | end do
|
318 | 329 |
|
319 | 330 | end function read_lines_expanded
|
320 | 331 |
|
321 | 332 | !> read lines into an array of TYPE(STRING_T) variables
|
322 |
| -function read_lines(fh) result(lines) |
323 |
| - integer, intent(in) :: fh |
| 333 | +function read_lines(filename) result(lines) |
| 334 | + character(len=*), intent(in) :: filename |
324 | 335 | type(string_t), allocatable :: lines(:)
|
325 | 336 |
|
326 | 337 | integer :: i
|
327 |
| - integer :: iostat |
| 338 | + character(len=:), allocatable :: content |
| 339 | + integer, allocatable :: first(:), last(:) |
328 | 340 |
|
329 |
| - allocate(lines(number_of_rows(fh))) |
330 |
| - do i = 1, size(lines) |
331 |
| - call getline(fh, lines(i)%s, iostat) |
| 341 | + content = read_text_file(filename) |
| 342 | + if (len(content) == 0) then |
| 343 | + allocate (lines(0)) |
| 344 | + return |
| 345 | + end if |
| 346 | + |
| 347 | + call split_first_last(content, eol, first, last) ! TODO: \r (< macOS X), \n (>=macOS X/Linux/Unix), \r\n (Windows) |
| 348 | + |
| 349 | + ! allocate lines from file content string |
| 350 | + allocate (lines(size(first))) |
| 351 | + do i = 1, size(first) |
| 352 | + allocate(lines(i)%s, source=content(first(i):last(i))) |
332 | 353 | end do
|
333 | 354 |
|
334 | 355 | end function read_lines
|
335 | 356 |
|
| 357 | +!> read text file into a string |
| 358 | +function read_text_file(filename) result(string) |
| 359 | + character(len=*), intent(in) :: filename |
| 360 | + character(len=:), allocatable :: string |
| 361 | + integer :: fh, length |
| 362 | + |
| 363 | + open (newunit=fh, file=filename, status='old', action='read', & |
| 364 | + access='stream', form='unformatted') |
| 365 | + inquire (fh, size=length) |
| 366 | + allocate (character(len=length) :: string) |
| 367 | + if (length == 0) return |
| 368 | + read (fh) string |
| 369 | + close (fh) |
| 370 | + |
| 371 | +end function read_text_file |
| 372 | + |
336 | 373 | !> Create a directory. Create subdirectories as needed
|
337 | 374 | subroutine mkdir(dir, echo)
|
338 | 375 | character(len=*), intent(in) :: dir
|
@@ -480,9 +517,8 @@ recursive subroutine list_files(dir, files, recurse)
|
480 | 517 | call fpm_stop(2,'*list_files*:directory listing failed')
|
481 | 518 | end if
|
482 | 519 |
|
483 |
| - open (newunit=fh, file=temp_file, status='old') |
484 |
| - files = read_lines(fh) |
485 |
| - close(fh,status="delete") |
| 520 | + files = read_lines(temp_file) |
| 521 | + call delete_file(temp_file) |
486 | 522 |
|
487 | 523 | do i=1,size(files)
|
488 | 524 | files(i)%s = join_path(dir,files(i)%s)
|
@@ -678,7 +714,7 @@ subroutine getline(unit, line, iostat, iomsg)
|
678 | 714 | !> Error message
|
679 | 715 | character(len=:), allocatable, optional :: iomsg
|
680 | 716 |
|
681 |
| - integer, parameter :: BUFFER_SIZE = 32768 |
| 717 | + integer, parameter :: BUFFER_SIZE = 1024 |
682 | 718 | character(len=BUFFER_SIZE) :: buffer
|
683 | 719 | character(len=256) :: msg
|
684 | 720 | integer :: size
|
|
0 commit comments