| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- MODULE FILES;
- IMPORT UTILS IN "./utils/UTILS.ob07", C := COLLECTIONS;
- TYPE
- FILE* = POINTER TO RECORD (C.ITEM)
- ptr: INTEGER;
- buffer: ARRAY 64*1024 OF BYTE;
- count: INTEGER
- END;
- VAR
- files: C.COLLECTION;
- PROCEDURE copy (src: ARRAY OF BYTE; src_idx: INTEGER; VAR dst: ARRAY OF BYTE; dst_idx: INTEGER; bytes: INTEGER);
- BEGIN
- WHILE bytes > 0 DO
- dst[dst_idx] := src[src_idx];
- INC(dst_idx);
- INC(src_idx);
- DEC(bytes)
- END
- END copy;
- PROCEDURE flush (file: FILE): INTEGER;
- VAR
- res: INTEGER;
- BEGIN
- IF file # NIL THEN
- res := UTILS.FileWrite(file.ptr, file.buffer, file.count);
- IF res < 0 THEN
- res := 0
- END
- ELSE
- res := 0
- END
- RETURN res
- END flush;
- PROCEDURE NewFile (): FILE;
- VAR
- file: FILE;
- citem: C.ITEM;
- BEGIN
- citem := C.pop(files);
- IF citem = NIL THEN
- NEW(file)
- ELSE
- file := citem(FILE)
- END
- RETURN file
- END NewFile;
- PROCEDURE create* (name: ARRAY OF CHAR): FILE;
- VAR
- file: FILE;
- ptr: INTEGER;
- BEGIN
- ptr := UTILS.FileCreate(name);
- IF ptr > 0 THEN
- file := NewFile();
- file.ptr := ptr;
- file.count := 0
- ELSE
- file := NIL
- END
- RETURN file
- END create;
- PROCEDURE open* (name: ARRAY OF CHAR): FILE;
- VAR
- file: FILE;
- ptr: INTEGER;
- BEGIN
- ptr := UTILS.FileOpen(name);
- IF ptr > 0 THEN
- file := NewFile();
- file.ptr := ptr;
- file.count := -1
- ELSE
- file := NIL
- END
- RETURN file
- END open;
- PROCEDURE close* (VAR file: FILE);
- VAR
- n: INTEGER;
- BEGIN
- IF file # NIL THEN
- IF file.count > 0 THEN
- n := flush(file)
- END;
- file.count := -1;
- UTILS.FileClose(file.ptr);
- file.ptr := 0;
- C.push(files, file);
- file := NIL
- END
- END close;
- PROCEDURE read* (file: FILE; VAR chunk: ARRAY OF CHAR; bytes: INTEGER): INTEGER;
- VAR
- res: INTEGER;
- BEGIN
- IF file # NIL THEN
- res := UTILS.FileRead(file.ptr, chunk, MAX(MIN(bytes, LEN(chunk)), 0));
- IF res < 0 THEN
- res := 0
- END
- ELSE
- res := 0
- END
- RETURN res
- END read;
- PROCEDURE write* (file: FILE; chunk: ARRAY OF BYTE; bytes: INTEGER): INTEGER;
- VAR
- free, n, idx: INTEGER;
- BEGIN
- idx := 0;
- IF (file # NIL) & (file.count >= 0) THEN
- free := LEN(file.buffer) - file.count;
- WHILE bytes > 0 DO
- n := MIN(free, bytes);
- copy(chunk, idx, file.buffer, file.count, n);
- DEC(free, n);
- DEC(bytes, n);
- INC(idx, n);
- INC(file.count, n);
- IF free = 0 THEN
- IF flush(file) # LEN(file.buffer) THEN
- bytes := 0;
- DEC(idx, n)
- ELSE
- file.count := 0;
- free := LEN(file.buffer)
- END
- END
- END
- END
- RETURN idx
- END write;
- PROCEDURE WriteByte* (file: FILE; byte: BYTE): BOOLEAN;
- VAR
- arr: ARRAY 1 OF BYTE;
- BEGIN
- arr[0] := byte
- RETURN write(file, arr, 1) = 1
- END WriteByte;
- BEGIN
- files := C.create()
- END FILES.
|