Skip to content

Commit 576b4f7

Browse files
authored
Merge pull request #1 from jvdp1/opencertik
stdlib_experimental_io: addition of a parser and characters "+" and "s/b" (for stream)
2 parents ab5c469 + 2f1a0e8 commit 576b4f7

File tree

3 files changed

+109
-20
lines changed

3 files changed

+109
-20
lines changed

src/stdlib_experimental_io.f90

Lines changed: 77 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -287,26 +287,85 @@ integer function open(filename, mode) result(u)
287287

288288
character(*), intent(in) :: filename
289289
character(*), intent(in), optional :: mode
290-
character(:), allocatable :: mode_
291-
mode_ = "rt"
292-
if (present(mode)) mode_ = mode
293-
! Note: the Fortran standard says that the default values for `status` and
294-
! `action` are processor dependent, so we have to explicitly set them below
295-
if (mode_ == "r" .or. mode_ == 'rt') then
296-
open(newunit=u, file=filename, status="old", action="read", &
297-
access='sequential', form='formatted')
298-
else if (mode_ == "w" .or. mode_ == "wt") then
299-
open(newunit=u, file=filename, status="replace", action="write", &
300-
access='sequential', form='formatted')
301-
else if (mode_ == "a" .or. mode_ == "at") then
302-
open(newunit=u, file=filename, position="append", status="old", &
303-
action="write", access='sequential', form='formatted')
304-
else if (mode_ == "x" .or. mode_ == "xt") then
305-
open(newunit=u, file=filename, status="new", &
306-
action="write", access='sequential', form='formatted')
290+
integer :: io
291+
character(3):: mode_
292+
character(:),allocatable :: action_, position_, status_, access_, form_
293+
294+
295+
mode_ = "r t"
296+
if (present(mode)) mode_ = parse_mode(mode)
297+
298+
if (mode_(1:2) == 'r ') then
299+
action_='read'
300+
position_='asis'
301+
status_='old'
302+
else if (mode_(1:2) == 'w ') then
303+
action_='write'
304+
position_='asis'
305+
status_='replace'
306+
else if (mode_(1:2) == 'a ') then
307+
action_='write'
308+
position_='append'
309+
status_='old'
310+
else if (mode_(1:2) == 'x ') then
311+
action_='write'
312+
position_='asis'
313+
status_='new'
314+
else if (mode_(1:2) == 'r+') then
315+
action_='readwrite'
316+
position_='asis'
317+
status_='old'
318+
else if (mode_(1:2) == 'w+') then
319+
action_='readwrite'
320+
position_='asis'
321+
status_='replace'
322+
else if (mode_(1:2) == 'a+') then
323+
action_='readwrite'
324+
position_='append'
325+
status_='old'
326+
else if (mode_(1:2) == 'x+') then
327+
action_='readwrite'
328+
position_='asis'
329+
status_='new'
307330
else
308-
call error_stop("Unsupported mode")
331+
call error_stop("Unsupported mode: "//mode_(1:2))
309332
end if
333+
334+
if (mode_(3:3) == 't') then
335+
access_='sequential'
336+
form_='formatted'
337+
else if (mode_(3:3) == 'b' .or. mode_(3:3) == 's') then
338+
access_='stream'
339+
form_='unformatted'
340+
else
341+
call error_stop("Unsupported mode: "//mode_(3:3))
342+
endif
343+
344+
open(newunit=u, file=filename, &
345+
action = action_, position = position_, status = status_, &
346+
access = access_, form = form_, &
347+
iostat = io)
348+
349+
end function
350+
351+
character(3) function parse_mode(mode) result(mode_)
352+
character(*), intent(in) :: mode
353+
354+
mode_ = 'r t'
355+
mode_(1:1) = mode(1:1)
356+
357+
if (len_trim(adjustl(mode)) > 1) then
358+
if (mode(2:2) == '+' )then
359+
mode_(2:2) = '+'
360+
else
361+
mode_(3:3) = mode(2:2)
362+
endif
363+
end if
364+
365+
if (len_trim(adjustl(mode)) > 2) then
366+
mode_(3:3) = mode(3:3)
367+
end if
368+
310369
end function
311370

312371
end module

src/tests/io/Makefile.manual

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,19 @@ OBJS = ../../stdlib_experimental_error.o \
55
.PHONY: all clean
66
.SUFFIXES: .f90 .o
77

8-
all: test_loadtxt test_savetxt
8+
all: test_loadtxt test_savetxt test_open
99

1010
test_loadtxt: test_loadtxt.f90 $(OBJS)
1111
$(FC) $(FCFLAGS) $(CPPFLAGS) $< -o $@ $(OBJS)
1212

1313
test_savetxt: test_savetxt.f90 $(OBJS)
1414
$(FC) $(FCFLAGS) $(CPPFLAGS) $< -o $@ $(OBJS)
1515

16+
test_open: test_open.f90 $(OBJS)
17+
$(FC) $(FCFLAGS) $(CPPFLAGS) $< -o $@ $(OBJS)
18+
1619
%.o: %.mod
1720

1821
clean:
19-
$(RM) test_loadtxt test_savetxt
22+
$(RM) test_loadtxt test_savetxt test_open
2023
$(RM) *.o *.mod

src/tests/io/test_open.f90

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ program test_open
66
character(:), allocatable :: filename
77
integer :: u, a(3)
88

9+
! Text file
910
filename = get_outpath() // "/io_open.dat"
1011

1112
! Test mode "w"
@@ -31,6 +32,32 @@ program test_open
3132
close(u)
3233

3334

35+
36+
! Stream file
37+
filename = get_outpath() // "/io_open.stream"
38+
39+
! Test mode "w"
40+
u = open(filename, "wb")
41+
write(u) 1, 2, 3
42+
close(u)
43+
44+
! Test mode "r"
45+
u = open(filename, "rb")
46+
read(u) a
47+
call assert(all(a == [1, 2, 3]))
48+
close(u)
49+
50+
! Test mode "a"
51+
u = open(filename, "ab")
52+
write(u) 4, 5, 6
53+
close(u)
54+
u = open(filename, "rb")
55+
read(u) a
56+
call assert(all(a == [1, 2, 3]))
57+
read(u) a
58+
call assert(all(a == [4, 5, 6]))
59+
close(u)
60+
3461
contains
3562

3663
function get_outpath() result(outpath)

0 commit comments

Comments
 (0)