Subversion Repositories Kolibri OS

Rev

Rev 7696 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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