FILES.ob07 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. MODULE FILES;
  2. IMPORT UTILS IN "./utils/UTILS.ob07", C := COLLECTIONS;
  3. TYPE
  4. FILE* = POINTER TO RECORD (C.ITEM)
  5. ptr: INTEGER;
  6. buffer: ARRAY 64*1024 OF BYTE;
  7. count: INTEGER
  8. END;
  9. VAR
  10. files: C.COLLECTION;
  11. PROCEDURE copy (src: ARRAY OF BYTE; src_idx: INTEGER; VAR dst: ARRAY OF BYTE; dst_idx: INTEGER; bytes: INTEGER);
  12. BEGIN
  13. WHILE bytes > 0 DO
  14. dst[dst_idx] := src[src_idx];
  15. INC(dst_idx);
  16. INC(src_idx);
  17. DEC(bytes)
  18. END
  19. END copy;
  20. PROCEDURE flush (file: FILE): INTEGER;
  21. VAR
  22. res: INTEGER;
  23. BEGIN
  24. IF file # NIL THEN
  25. res := UTILS.FileWrite(file.ptr, file.buffer, file.count);
  26. IF res < 0 THEN
  27. res := 0
  28. END
  29. ELSE
  30. res := 0
  31. END
  32. RETURN res
  33. END flush;
  34. PROCEDURE NewFile (): FILE;
  35. VAR
  36. file: FILE;
  37. citem: C.ITEM;
  38. BEGIN
  39. citem := C.pop(files);
  40. IF citem = NIL THEN
  41. NEW(file)
  42. ELSE
  43. file := citem(FILE)
  44. END
  45. RETURN file
  46. END NewFile;
  47. PROCEDURE create* (name: ARRAY OF CHAR): FILE;
  48. VAR
  49. file: FILE;
  50. ptr: INTEGER;
  51. BEGIN
  52. ptr := UTILS.FileCreate(name);
  53. IF ptr > 0 THEN
  54. file := NewFile();
  55. file.ptr := ptr;
  56. file.count := 0
  57. ELSE
  58. file := NIL
  59. END
  60. RETURN file
  61. END create;
  62. PROCEDURE open* (name: ARRAY OF CHAR): FILE;
  63. VAR
  64. file: FILE;
  65. ptr: INTEGER;
  66. BEGIN
  67. ptr := UTILS.FileOpen(name);
  68. IF ptr > 0 THEN
  69. file := NewFile();
  70. file.ptr := ptr;
  71. file.count := -1
  72. ELSE
  73. file := NIL
  74. END
  75. RETURN file
  76. END open;
  77. PROCEDURE close* (VAR file: FILE);
  78. VAR
  79. n: INTEGER;
  80. BEGIN
  81. IF file # NIL THEN
  82. IF file.count > 0 THEN
  83. n := flush(file)
  84. END;
  85. file.count := -1;
  86. UTILS.FileClose(file.ptr);
  87. file.ptr := 0;
  88. C.push(files, file);
  89. file := NIL
  90. END
  91. END close;
  92. PROCEDURE read* (file: FILE; VAR chunk: ARRAY OF CHAR; bytes: INTEGER): INTEGER;
  93. VAR
  94. res: INTEGER;
  95. BEGIN
  96. IF file # NIL THEN
  97. res := UTILS.FileRead(file.ptr, chunk, MAX(MIN(bytes, LEN(chunk)), 0));
  98. IF res < 0 THEN
  99. res := 0
  100. END
  101. ELSE
  102. res := 0
  103. END
  104. RETURN res
  105. END read;
  106. PROCEDURE write* (file: FILE; chunk: ARRAY OF BYTE; bytes: INTEGER): INTEGER;
  107. VAR
  108. free, n, idx: INTEGER;
  109. BEGIN
  110. idx := 0;
  111. IF (file # NIL) & (file.count >= 0) THEN
  112. free := LEN(file.buffer) - file.count;
  113. WHILE bytes > 0 DO
  114. n := MIN(free, bytes);
  115. copy(chunk, idx, file.buffer, file.count, n);
  116. DEC(free, n);
  117. DEC(bytes, n);
  118. INC(idx, n);
  119. INC(file.count, n);
  120. IF free = 0 THEN
  121. IF flush(file) # LEN(file.buffer) THEN
  122. bytes := 0;
  123. DEC(idx, n)
  124. ELSE
  125. file.count := 0;
  126. free := LEN(file.buffer)
  127. END
  128. END
  129. END
  130. END
  131. RETURN idx
  132. END write;
  133. PROCEDURE WriteByte* (file: FILE; byte: BYTE): BOOLEAN;
  134. VAR
  135. arr: ARRAY 1 OF BYTE;
  136. BEGIN
  137. arr[0] := byte
  138. RETURN write(file, arr, 1) = 1
  139. END WriteByte;
  140. BEGIN
  141. files := C.create()
  142. END FILES.