Skip to content

Commit a0d9e22

Browse files
authored
stdlib_system: essential path functionality (#999)
2 parents 3385843 + a21a48b commit a0d9e22

11 files changed

+741
-13
lines changed

doc/specs/stdlib_system.md

Lines changed: 183 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ The result is a real value representing the elapsed time in seconds, measured fr
174174

175175
### Syntax
176176

177-
`delta_t = ` [[stdlib_system(module):elapsed(subroutine)]] `(process)`
177+
`delta_t = ` [[stdlib_system(module):elapsed(interface)]] `(process)`
178178

179179
### Arguments
180180

@@ -212,7 +212,7 @@ in case of process hang or delay.
212212

213213
### Syntax
214214

215-
`call ` [[stdlib_system(module):wait(subroutine)]] `(process [, max_wait_time])`
215+
`call ` [[stdlib_system(module):wait(interface)]] `(process [, max_wait_time])`
216216

217217
### Arguments
218218

@@ -243,7 +243,7 @@ This is especially useful for monitoring asynchronous processes and retrieving t
243243

244244
### Syntax
245245

246-
`call ` [[stdlib_system(module):update(subroutine)]] `(process)`
246+
`call ` [[stdlib_system(module):update(interface)]] `(process)`
247247

248248
### Arguments
249249

@@ -269,7 +269,7 @@ This interface is useful when a process needs to be forcefully stopped, for exam
269269

270270
### Syntax
271271

272-
`call ` [[stdlib_system(module):kill(subroutine)]] `(process, success)`
272+
`call ` [[stdlib_system(module):kill(interface)]] `(process, success)`
273273

274274
### Arguments
275275

@@ -298,7 +298,7 @@ It ensures that the requested sleep duration is honored on both Windows and Unix
298298

299299
### Syntax
300300

301-
`call ` [[stdlib_system(module):sleep(subroutine)]] `(millisec)`
301+
`call ` [[stdlib_system(module):sleep(interface)]] `(millisec)`
302302

303303
### Arguments
304304

@@ -324,7 +324,7 @@ This function is highly efficient and works during the compilation phase, avoidi
324324

325325
### Syntax
326326

327-
`result = ` [[stdlib_system(module):is_windows(function)]] `()`
327+
`result = ` [[stdlib_system(module):is_windows(interface)]] `()`
328328

329329
### Return Value
330330

@@ -359,7 +359,7 @@ If the OS cannot be identified, the function returns `OS_UNKNOWN`.
359359

360360
### Syntax
361361

362-
`os = [[stdlib_system(module):get_runtime_os(function)]]()`
362+
`os = ` [[stdlib_system(module):get_runtime_os(function)]] `()`
363363

364364
### Class
365365

@@ -396,7 +396,7 @@ This caching mechanism ensures negligible overhead for repeated calls, unlike `g
396396

397397
### Syntax
398398

399-
`os = [[stdlib_system(module):OS_TYPE(function)]]()`
399+
`os = ` [[stdlib_system(module):OS_TYPE(function)]]`()`
400400

401401
### Class
402402

@@ -431,7 +431,7 @@ It is designed to work across multiple platforms. On Windows, paths with both fo
431431

432432
### Syntax
433433

434-
`result = [[stdlib_system(module):is_directory(function)]] (path)`
434+
`result = ` [[stdlib_system(module):is_directory(function)]]`(path)`
435435

436436
### Class
437437

@@ -471,7 +471,7 @@ It reads as an empty file. The null device's path varies by operating system:
471471

472472
### Syntax
473473

474-
`path = [[stdlib_system(module):null_device(function)]]()`
474+
`path = ` [[stdlib_system(module):null_device(function)]]`()`
475475

476476
### Class
477477

@@ -506,7 +506,7 @@ The function provides an optional error-handling mechanism via the `state_type`
506506

507507
### Syntax
508508

509-
`call [[stdlib_system(module):delete_file(subroutine)]] (path [, err])`
509+
`call ` [[stdlib_system(module):delete_file(subroutine)]]` (path [, err])`
510510

511511
### Class
512512
Subroutine
@@ -532,3 +532,175 @@ The file is removed from the filesystem if the operation is successful. If the o
532532
```fortran
533533
{!example/system/example_delete_file.f90!}
534534
```
535+
536+
## `join_path` - Joins the provided paths according to the OS
537+
538+
### Status
539+
540+
Experimental
541+
542+
### Description
543+
544+
This interface joins the paths provided to it according to the platform specific path-separator.
545+
i.e `\` for windows and `/` for others
546+
547+
### Syntax
548+
549+
`res = ` [[stdlib_system(module):join_path(interface)]] ` (p1, p2)`
550+
551+
`res = ` [[stdlib_system(module):join_path(interface)]] ` (p)`
552+
553+
### Class
554+
Pure function
555+
556+
### Arguments
557+
558+
`p1, p2`: Shall be a character string or `type(string_type)`. It is an `intent(in)` argument.
559+
or
560+
`p`: Shall be a list of character strings or list of `type(string_type)`. It is an `intent(in)` argument.
561+
562+
### Return values
563+
564+
The resultant path, either a character string or `type(string_type)`.
565+
566+
## `operator(/)`
567+
568+
Alternative syntax to`join_path` using an overloaded operator. Join two paths according to the platform specific path-separator.
569+
570+
### Status
571+
572+
Experimental
573+
574+
### Syntax
575+
576+
`p = lval / rval`
577+
578+
### Class
579+
580+
Pure function.
581+
582+
### Arguments
583+
584+
`lval`: A character string or `type(string_type)`. It is an `intent(in)` argument.
585+
586+
`rval`: A character string or `type(string_type)`. It is an `intent(in)` argument.
587+
588+
### Result value
589+
590+
The result is an `allocatable` character string or `type(string_type)`
591+
592+
#### Example
593+
594+
```fortran
595+
{!example/system/example_path_join.f90!}
596+
```
597+
598+
## `split_path` - splits a path immediately following the last separator
599+
600+
### Status
601+
602+
Experimental
603+
604+
### Description
605+
606+
This subroutine splits a path immediately following the last separator after removing the trailing separators
607+
splitting it into most of the times a directory and a file name.
608+
609+
### Syntax
610+
611+
`call `[[stdlib_system(module):split_path(interface)]]`(p, head, tail)`
612+
613+
### Class
614+
Subroutine
615+
616+
### Arguments
617+
618+
`p`: A character string or `type(string_type)` containing the path to be split. It is an `intent(in)` argument.
619+
`head`: The first part of the path. Either a character string or `type(string_type)`. It is an `intent(out)` argument.
620+
`tail`: The rest part of the path. Either a character string or `type(string_type)`. It is an `intent(out)` argument.
621+
622+
### Behavior
623+
624+
- If `p` is empty, `head` is set to `.` and `tail` is left empty.
625+
- If `p` consists entirely of path-separators, `head` is set to the path-separator and `tail` is left empty.
626+
- `head` ends with a path-separator if and only if `p` appears to be a root directory or child of one.
627+
628+
### Return values
629+
630+
The splitted path. `head` and `tail`.
631+
632+
### Example
633+
634+
```fortran
635+
{!example/system/example_path_split_path.f90!}
636+
```
637+
638+
## `base_name` - The last part of a path
639+
640+
### Status
641+
642+
Experimental
643+
644+
### Description
645+
646+
This function returns the last part of a path after removing trailing path separators.
647+
648+
### Syntax
649+
650+
`res = ` [[stdlib_system(module):base_name(interface)]]`(p)`
651+
652+
### Class
653+
Function
654+
655+
### Arguments
656+
657+
`p`: the path, a character string or `type(string_type)`. It is an `intent(in)` argument.
658+
659+
### Behavior
660+
661+
- The `tail` of `[[stdlib_system(module):split_path(interface)]]` is exactly what is returned. Same Behavior.
662+
663+
### Return values
664+
665+
A character string or `type(string_type)`.
666+
667+
### Example
668+
669+
```fortran
670+
{!example/system/example_path_base_name.f90!}
671+
```
672+
673+
## `dir_name` - Everything except the last part of the path
674+
675+
### Status
676+
677+
Experimental
678+
679+
### Description
680+
681+
This function returns everything except the last part of a path.
682+
683+
### Syntax
684+
685+
`res = ` [[stdlib_system(module):dir_name(interface)]]`(p)`
686+
687+
### Class
688+
Function
689+
690+
### Arguments
691+
692+
`p`: the path, a character string or `type(string_type)`. It is an `intent(in)` argument.
693+
694+
### Behavior
695+
696+
- The `head` of `[[stdlib_system(module):split_path(interface)]]` is exactly what is returned. Same Behavior.
697+
698+
### Return values
699+
700+
A character string or `type(string_type)`.
701+
702+
### Example
703+
704+
```fortran
705+
{!example/system/example_path_dir_name.f90!}
706+
```

example/system/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,7 @@ ADD_EXAMPLE(process_5)
1111
ADD_EXAMPLE(process_6)
1212
ADD_EXAMPLE(process_7)
1313
ADD_EXAMPLE(sleep)
14+
ADD_EXAMPLE(path_join)
15+
ADD_EXAMPLE(path_split_path)
16+
ADD_EXAMPLE(path_base_name)
17+
ADD_EXAMPLE(path_dir_name)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
! Usage of base_name
2+
program example_path_base_name
3+
use stdlib_system, only: base_name, OS_TYPE, OS_WINDOWS
4+
character(len=:), allocatable :: p1
5+
6+
if(OS_TYPE() == OS_WINDOWS) then
7+
p1 = 'C:\Users'
8+
else
9+
p1 = '/home'
10+
endif
11+
12+
print *, 'base name of '// p1 // ' -> ' // base_name(p1)
13+
! base name of C:\Users -> Users
14+
! OR
15+
! base name of /home -> home
16+
end program example_path_base_name
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
! Usage of dir_name
2+
program example_path_dir_name
3+
use stdlib_system, only: dir_name, OS_TYPE, OS_WINDOWS
4+
character(len=:), allocatable :: p1, head, tail
5+
6+
if(OS_TYPE() == OS_WINDOWS) then
7+
p1 = 'C:\Users' ! C:\Users
8+
else
9+
p1 = '/home' ! /home
10+
endif
11+
12+
print *, 'dir_name of '// p1 // ' -> ' // dir_name(p1)
13+
! dir_name of C:\Users -> C:\
14+
! OR
15+
! dir_name of /home -> /
16+
end program example_path_dir_name

example/system/example_path_join.f90

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
! Usage of join_path, operator(/)
2+
program example_path_join
3+
use stdlib_system, only: join_path, operator(/), OS_TYPE, OS_WINDOWS
4+
character(len=:), allocatable :: p1, p2, p3
5+
character(len=20) :: parr(4)
6+
7+
if(OS_TYPE() == OS_WINDOWS) then
8+
p1 = 'C:'/'Users'/'User1'/'Desktop'
9+
p2 = join_path('C:\Users\User1', 'Desktop')
10+
parr = [character(len=20) :: 'C:', 'Users', 'User1', 'Desktop']
11+
p3 = join_path(parr)
12+
else
13+
p1 = ''/'home'/'User1'/'Desktop'
14+
p2 = join_path('/home/User1', 'Desktop')
15+
parr = [character(len=20) :: '', 'home', 'User1', 'Desktop']
16+
p3 = join_path(parr)
17+
end if
18+
19+
! (p1 == p2 == p3) = '/home/User1/Desktop' OR 'C:\Users\User1\Desktop'
20+
print *, p1 ! /home/User1/Desktop OR 'C:\Users\User1\Desktop'
21+
print *, "p1 == p2: ", p1 == p2 ! T
22+
print *, "p2 == p3: ", p2 == p3 ! T
23+
end program example_path_join
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
! Usage of split_path
2+
program example_path_split_path
3+
use stdlib_system, only: join_path, split_path, OS_TYPE, OS_WINDOWS
4+
character(len=:), allocatable :: p1, head, tail
5+
6+
if(OS_TYPE() == OS_WINDOWS) then
7+
p1 = join_path('C:\Users\User1', 'Desktop') ! C:\Users\User1\Desktop
8+
else
9+
p1 = join_path('/home/User1', 'Desktop') ! /home/User1/Desktop
10+
endif
11+
12+
call split_path(p1, head, tail)
13+
! head = /home/User1 OR C:\Users\User1, tail = Desktop
14+
print *, p1 // " -> " // head // " + " // tail
15+
! C:\Users\User1\Desktop -> C:\Users\User1 + Desktop
16+
! OR
17+
! /home/User1/Desktop -> /home/User1 + Desktop
18+
19+
call split_path(head, p1, tail)
20+
! p1 = /home OR C:\Users, tail = User1
21+
print *, head // " -> " // p1 // " + " // tail
22+
! C:\Users\User1 -> C:\Users + User1
23+
! OR
24+
! /home/User1 -> /home + User1
25+
end program example_path_split_path

src/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ set(fppFiles
9393
# Preprocessed files to contain preprocessor directives -> .F90
9494
set(cppFiles
9595
stdlib_linalg_constants.fypp
96-
9796
stdlib_linalg_blas.fypp
9897
stdlib_linalg_lapack.fypp
9998
)
@@ -118,6 +117,7 @@ set(SRC
118117
stdlib_sorting_radix_sort.f90
119118
stdlib_system_subprocess.c
120119
stdlib_system_subprocess.F90
120+
stdlib_system_path.f90
121121
stdlib_system.F90
122122
stdlib_sparse.f90
123123
stdlib_specialfunctions_legendre.f90

0 commit comments

Comments
 (0)