CHUNKLISTS.ob07 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. (*
  2. BSD 2-Clause License
  3. Copyright (c) 2018-2021, Anton Krotov
  4. All rights reserved.
  5. *)
  6. MODULE CHUNKLISTS;
  7. IMPORT LISTS, WR := WRITER;
  8. CONST
  9. LENOFBYTECHUNK = 65536;
  10. LENOFINTCHUNK = 16384;
  11. TYPE
  12. ANYLIST = POINTER TO RECORD (LISTS.LIST)
  13. length: INTEGER
  14. END;
  15. BYTELIST* = POINTER TO RECORD (ANYLIST) END;
  16. BYTECHUNK = POINTER TO RECORD (LISTS.ITEM)
  17. data: ARRAY LENOFBYTECHUNK OF BYTE;
  18. count: INTEGER
  19. END;
  20. INTLIST* = POINTER TO RECORD (ANYLIST) END;
  21. INTCHUNK = POINTER TO RECORD (LISTS.ITEM)
  22. data: ARRAY LENOFINTCHUNK OF INTEGER;
  23. count: INTEGER
  24. END;
  25. PROCEDURE SetByte* (list: BYTELIST; idx: INTEGER; byte: BYTE);
  26. VAR
  27. chunk: BYTECHUNK;
  28. item: LISTS.ITEM;
  29. BEGIN
  30. ASSERT(idx >= 0);
  31. ASSERT(list # NIL);
  32. item := LISTS.getidx(list, idx DIV LENOFBYTECHUNK);
  33. ASSERT(item # NIL);
  34. chunk := item(BYTECHUNK);
  35. idx := idx MOD LENOFBYTECHUNK;
  36. ASSERT(idx < chunk.count);
  37. chunk.data[idx] := byte
  38. END SetByte;
  39. PROCEDURE GetByte* (list: BYTELIST; idx: INTEGER): BYTE;
  40. VAR
  41. chunk: BYTECHUNK;
  42. item: LISTS.ITEM;
  43. BEGIN
  44. ASSERT(idx >= 0);
  45. ASSERT(list # NIL);
  46. item := LISTS.getidx(list, idx DIV LENOFBYTECHUNK);
  47. ASSERT(item # NIL);
  48. chunk := item(BYTECHUNK);
  49. idx := idx MOD LENOFBYTECHUNK;
  50. ASSERT(idx < chunk.count)
  51. RETURN chunk.data[idx]
  52. END GetByte;
  53. PROCEDURE PushByte* (list: BYTELIST; byte: BYTE);
  54. VAR
  55. chunk: BYTECHUNK;
  56. BEGIN
  57. ASSERT(list # NIL);
  58. chunk := list.last(BYTECHUNK);
  59. IF chunk.count = LENOFBYTECHUNK THEN
  60. NEW(chunk);
  61. chunk.count := 0;
  62. LISTS.push(list, chunk)
  63. END;
  64. chunk.data[chunk.count] := byte;
  65. INC(chunk.count);
  66. INC(list.length)
  67. END PushByte;
  68. PROCEDURE PushStr* (list: BYTELIST; str: ARRAY OF CHAR): INTEGER;
  69. VAR
  70. i, res: INTEGER;
  71. BEGIN
  72. res := list.length;
  73. i := 0;
  74. REPEAT
  75. PushByte(list, ORD(str[i]));
  76. INC(i)
  77. UNTIL str[i - 1] = 0X
  78. RETURN res
  79. END PushStr;
  80. PROCEDURE GetStr* (list: BYTELIST; pos: INTEGER; VAR str: ARRAY OF CHAR): BOOLEAN;
  81. VAR
  82. i: INTEGER;
  83. res: BOOLEAN;
  84. BEGIN
  85. res := FALSE;
  86. i := 0;
  87. WHILE (pos < list.length) & (i < LEN(str)) & ~res DO
  88. str[i] := CHR(GetByte(list, pos));
  89. res := str[i] = 0X;
  90. INC(pos);
  91. INC(i)
  92. END
  93. RETURN res
  94. END GetStr;
  95. PROCEDURE WriteToFile* (list: BYTELIST);
  96. VAR
  97. chunk: BYTECHUNK;
  98. BEGIN
  99. chunk := list.first(BYTECHUNK);
  100. WHILE chunk # NIL DO
  101. WR.Write(chunk.data, chunk.count);
  102. chunk := chunk.next(BYTECHUNK)
  103. END
  104. END WriteToFile;
  105. PROCEDURE CreateByteList* (): BYTELIST;
  106. VAR
  107. bytelist: BYTELIST;
  108. list: LISTS.LIST;
  109. chunk: BYTECHUNK;
  110. BEGIN
  111. NEW(bytelist);
  112. list := LISTS.create(bytelist);
  113. bytelist.length := 0;
  114. NEW(chunk);
  115. chunk.count := 0;
  116. LISTS.push(list, chunk)
  117. RETURN list(BYTELIST)
  118. END CreateByteList;
  119. PROCEDURE SetInt* (list: INTLIST; idx: INTEGER; int: INTEGER);
  120. VAR
  121. chunk: INTCHUNK;
  122. item: LISTS.ITEM;
  123. BEGIN
  124. ASSERT(idx >= 0);
  125. ASSERT(list # NIL);
  126. item := LISTS.getidx(list, idx DIV LENOFINTCHUNK);
  127. ASSERT(item # NIL);
  128. chunk := item(INTCHUNK);
  129. idx := idx MOD LENOFINTCHUNK;
  130. ASSERT(idx < chunk.count);
  131. chunk.data[idx] := int
  132. END SetInt;
  133. PROCEDURE GetInt* (list: INTLIST; idx: INTEGER): INTEGER;
  134. VAR
  135. chunk: INTCHUNK;
  136. item: LISTS.ITEM;
  137. BEGIN
  138. ASSERT(idx >= 0);
  139. ASSERT(list # NIL);
  140. item := LISTS.getidx(list, idx DIV LENOFINTCHUNK);
  141. ASSERT(item # NIL);
  142. chunk := item(INTCHUNK);
  143. idx := idx MOD LENOFINTCHUNK;
  144. ASSERT(idx < chunk.count)
  145. RETURN chunk.data[idx]
  146. END GetInt;
  147. PROCEDURE PushInt* (list: INTLIST; int: INTEGER);
  148. VAR
  149. chunk: INTCHUNK;
  150. BEGIN
  151. ASSERT(list # NIL);
  152. chunk := list.last(INTCHUNK);
  153. IF chunk.count = LENOFINTCHUNK THEN
  154. NEW(chunk);
  155. chunk.count := 0;
  156. LISTS.push(list, chunk)
  157. END;
  158. chunk.data[chunk.count] := int;
  159. INC(chunk.count);
  160. INC(list.length)
  161. END PushInt;
  162. PROCEDURE CreateIntList* (): INTLIST;
  163. VAR
  164. intlist: INTLIST;
  165. list: LISTS.LIST;
  166. chunk: INTCHUNK;
  167. BEGIN
  168. NEW(intlist);
  169. list := LISTS.create(intlist);
  170. intlist.length := 0;
  171. NEW(chunk);
  172. chunk.count := 0;
  173. LISTS.push(list, chunk)
  174. RETURN list(INTLIST)
  175. END CreateIntList;
  176. PROCEDURE Length* (list: ANYLIST): INTEGER;
  177. RETURN list.length
  178. END Length;
  179. END CHUNKLISTS.