CHUNKLISTS.ob07 5.1 KB

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