Subversion Repositories Kolibri OS

Rev

Rev 8097 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. (*
  2.     BSD 2-Clause License
  3.  
  4.     Copyright (c) 2018-2021, Anton Krotov
  5.     All rights reserved.
  6. *)
  7.  
  8. MODULE FILES;
  9.  
  10. IMPORT UTILS, C := COLLECTIONS, CONSOLE;
  11.  
  12.  
  13. TYPE
  14.  
  15.     FILE* = POINTER TO RECORD (C.ITEM)
  16.  
  17.         ptr: INTEGER;
  18.  
  19.         buffer: ARRAY 64*1024 OF BYTE;
  20.         count:  INTEGER
  21.  
  22.     END;
  23.  
  24. VAR
  25.  
  26.     files: C.COLLECTION;
  27.  
  28.  
  29. PROCEDURE copy (src: ARRAY OF BYTE; src_idx: INTEGER; VAR dst: ARRAY OF BYTE; dst_idx: INTEGER; bytes: INTEGER);
  30. BEGIN
  31.     WHILE bytes > 0 DO
  32.         dst[dst_idx] := src[src_idx];
  33.         INC(dst_idx);
  34.         INC(src_idx);
  35.         DEC(bytes)
  36.     END
  37. END copy;
  38.  
  39.  
  40. PROCEDURE flush (file: FILE): INTEGER;
  41. VAR
  42.     res: INTEGER;
  43.  
  44. BEGIN
  45.     IF file # NIL THEN
  46.         res := UTILS.FileWrite(file.ptr, file.buffer, file.count);
  47.         IF res < 0 THEN
  48.             res := 0
  49.         END
  50.     ELSE
  51.         res := 0
  52.     END
  53.  
  54.     RETURN res
  55. END flush;
  56.  
  57.  
  58. PROCEDURE NewFile (): FILE;
  59. VAR
  60.     file:  FILE;
  61.     citem: C.ITEM;
  62.  
  63. BEGIN
  64.     citem := C.pop(files);
  65.     IF citem = NIL THEN
  66.         NEW(file)
  67.     ELSE
  68.         file := citem(FILE)
  69.     END
  70.  
  71.     RETURN file
  72. END NewFile;
  73.  
  74.  
  75. PROCEDURE create* (name: ARRAY OF CHAR): FILE;
  76. VAR
  77.     file: FILE;
  78.     ptr:  INTEGER;
  79.  
  80. BEGIN
  81.     ptr := UTILS.FileCreate(name);
  82.  
  83.     IF ptr > 0 THEN
  84.         file := NewFile();
  85.         file.ptr := ptr;
  86.         file.count := 0
  87.     ELSE
  88.         file := NIL
  89.     END
  90.  
  91.     RETURN file
  92. END create;
  93.  
  94.  
  95. PROCEDURE open* (name: ARRAY OF CHAR): FILE;
  96. VAR
  97.     file: FILE;
  98.     ptr:  INTEGER;
  99.  
  100. BEGIN
  101.     ptr := UTILS.FileOpen(name);
  102.  
  103.     IF ptr > 0 THEN
  104.         file := NewFile();
  105.         file.ptr := ptr;
  106.         file.count := -1
  107.     ELSE
  108.         file := NIL
  109.     END
  110.  
  111.     RETURN file
  112. END open;
  113.  
  114.  
  115. PROCEDURE close* (VAR file: FILE);
  116. VAR
  117.     n: INTEGER;
  118.  
  119. BEGIN
  120.     IF file # NIL THEN
  121.  
  122.         IF file.count > 0 THEN
  123.             n := flush(file)
  124.         END;
  125.  
  126.         file.count := -1;
  127.  
  128.         UTILS.FileClose(file.ptr);
  129.         file.ptr := 0;
  130.  
  131.         C.push(files, file);
  132.         file := NIL
  133.     END
  134. END close;
  135.  
  136.  
  137. PROCEDURE read* (file: FILE; VAR chunk: ARRAY OF CHAR; bytes: INTEGER): INTEGER;
  138. VAR
  139.     res: INTEGER;
  140.  
  141. BEGIN
  142.     IF file # NIL THEN
  143.         res := UTILS.FileRead(file.ptr, chunk, MAX(MIN(bytes, LEN(chunk)), 0));
  144.         IF res < 0 THEN
  145.             res := 0
  146.         END
  147.     ELSE
  148.         res := 0
  149.     END
  150.  
  151.     RETURN res
  152. END read;
  153.  
  154.  
  155. PROCEDURE write* (file: FILE; chunk: ARRAY OF BYTE; bytes: INTEGER): INTEGER;
  156. VAR
  157.     free, n, idx: INTEGER;
  158.  
  159. BEGIN
  160.     idx := 0;
  161.     IF (file # NIL) & (file.count >= 0) THEN
  162.  
  163.         free := LEN(file.buffer) - file.count;
  164.         WHILE bytes > 0 DO
  165.             n := MIN(free, bytes);
  166.             copy(chunk, idx, file.buffer, file.count, n);
  167.             DEC(free, n);
  168.             DEC(bytes, n);
  169.             INC(idx, n);
  170.             INC(file.count, n);
  171.             IF free = 0 THEN
  172.                 IF flush(file) # LEN(file.buffer) THEN
  173.                     bytes := 0;
  174.                     DEC(idx, n)
  175.                 ELSE
  176.                     file.count := 0;
  177.                     free := LEN(file.buffer)
  178.                 END
  179.             END
  180.         END
  181.  
  182.     END
  183.  
  184.     RETURN idx
  185. END write;
  186.  
  187.  
  188. PROCEDURE WriteByte* (file: FILE; byte: BYTE): BOOLEAN;
  189. VAR
  190.     arr: ARRAY 1 OF BYTE;
  191.  
  192. BEGIN
  193.     arr[0] := byte
  194.     RETURN write(file, arr, 1) = 1
  195. END WriteByte;
  196.  
  197.  
  198. BEGIN
  199.     files := C.create()
  200. END FILES.