Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 7596 → Rev 7597

/programs/develop/oberon07/Source/FILES.ob07
0,0 → 1,219
(*
BSD 2-Clause License
 
Copyright (c) 2018, Anton Krotov
All rights reserved.
*)
 
MODULE FILES;
 
IMPORT UTILS, C := COLLECTIONS, CONSOLE;
 
 
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 BYTE; 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, k, res, idx: INTEGER;
 
BEGIN
idx := 0;
res := 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);
INC(res, n);
DEC(free, n);
DEC(bytes, n);
INC(idx, n);
INC(file.count, n);
IF free = 0 THEN
k := flush(file);
IF k # LEN(file.buffer) THEN
bytes := 0;
DEC(res, n)
ELSE
file.count := 0;
free := LEN(file.buffer)
END
END
END
 
END
 
RETURN res
END write;
 
 
PROCEDURE WriteByte* (file: FILE; byte: BYTE): BOOLEAN;
VAR
res: BOOLEAN;
 
BEGIN
res := TRUE;
IF (file # NIL) & (file.count >= 0) THEN
IF file.count = LEN(file.buffer) THEN
IF flush(file) # LEN(file.buffer) THEN
res := FALSE
ELSE
file.buffer[0] := byte;
file.count := 1
END
ELSE
file.buffer[file.count] := byte;
INC(file.count)
END
ELSE
res := FALSE
END
 
RETURN res
END WriteByte;
 
 
BEGIN
files := C.create()
END FILES.