Subversion Repositories Kolibri OS

Rev

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

  1. (*
  2.     BSD 2-Clause License
  3.  
  4.     Copyright (c) 2018, 2019, Anton Krotov
  5.     All rights reserved.
  6. *)
  7.  
  8. MODULE CHUNKLISTS;
  9.  
  10. IMPORT LISTS, WR := WRITER;
  11.  
  12.  
  13. CONST
  14.  
  15.     LENOFBYTECHUNK = 64000;
  16.     LENOFINTCHUNK  = 16000;
  17.  
  18.  
  19. TYPE
  20.  
  21.     ANYLIST = POINTER TO RECORD (LISTS.LIST)
  22.  
  23.         length: INTEGER
  24.  
  25.     END;
  26.  
  27.     BYTELIST* = POINTER TO RECORD (ANYLIST) END;
  28.  
  29.     BYTECHUNK = POINTER TO RECORD (LISTS.ITEM)
  30.  
  31.         data:   ARRAY LENOFBYTECHUNK OF BYTE;
  32.         count:  INTEGER
  33.  
  34.     END;
  35.  
  36.  
  37.     INTLIST* = POINTER TO RECORD (ANYLIST) END;
  38.  
  39.     INTCHUNK = POINTER TO RECORD (LISTS.ITEM)
  40.  
  41.         data:   ARRAY LENOFINTCHUNK OF INTEGER;
  42.         count:  INTEGER
  43.  
  44.     END;
  45.  
  46.  
  47. PROCEDURE SetByte* (list: BYTELIST; idx: INTEGER; byte: BYTE);
  48. VAR
  49.     ChunkNum: INTEGER;
  50.     chunk:    BYTECHUNK;
  51.  
  52. BEGIN
  53.     ASSERT(idx >= 0);
  54.     ASSERT(list # NIL);
  55.  
  56.     ChunkNum := idx DIV LENOFBYTECHUNK;
  57.     idx      := idx MOD LENOFBYTECHUNK;
  58.  
  59.     chunk := list.first(BYTECHUNK);
  60.  
  61.     WHILE (chunk # NIL) & (ChunkNum > 0) DO
  62.         chunk := chunk.next(BYTECHUNK);
  63.         DEC(ChunkNum)
  64.     END;
  65.  
  66.     ASSERT(chunk # NIL);
  67.     ASSERT(idx < chunk.count);
  68.  
  69.     chunk.data[idx] := byte
  70. END SetByte;
  71.  
  72.  
  73. PROCEDURE GetByte* (list: BYTELIST; idx: INTEGER): BYTE;
  74. VAR
  75.     ChunkNum: INTEGER;
  76.     chunk:    BYTECHUNK;
  77.  
  78. BEGIN
  79.     ASSERT(idx >= 0);
  80.     ASSERT(list # NIL);
  81.  
  82.     ChunkNum := idx DIV LENOFBYTECHUNK;
  83.     idx      := idx MOD LENOFBYTECHUNK;
  84.  
  85.     chunk := list.first(BYTECHUNK);
  86.  
  87.     WHILE (chunk # NIL) & (ChunkNum > 0) DO
  88.         chunk := chunk.next(BYTECHUNK);
  89.         DEC(ChunkNum)
  90.     END;
  91.  
  92.     ASSERT(chunk # NIL);
  93.     ASSERT(idx < chunk.count)
  94.  
  95.     RETURN chunk.data[idx]
  96. END GetByte;
  97.  
  98.  
  99. PROCEDURE PushByte* (list: BYTELIST; byte: BYTE);
  100. VAR
  101.     chunk: BYTECHUNK;
  102.  
  103. BEGIN
  104.     ASSERT(list # NIL);
  105.  
  106.     chunk := list.last(BYTECHUNK);
  107.  
  108.     IF chunk.count = LENOFBYTECHUNK THEN
  109.         NEW(chunk);
  110.         chunk.count := 0;
  111.         LISTS.push(list, chunk)
  112.     END;
  113.  
  114.     chunk.data[chunk.count] := byte;
  115.     INC(chunk.count);
  116.  
  117.     INC(list.length)
  118. END PushByte;
  119.  
  120.  
  121. PROCEDURE PushStr* (list: BYTELIST; str: ARRAY OF CHAR): INTEGER;
  122. VAR
  123.     i, res: INTEGER;
  124.  
  125. BEGIN
  126.     res := list.length;
  127.     i := 0;
  128.     REPEAT
  129.         PushByte(list, ORD(str[i]));
  130.         INC(i)
  131.     UNTIL str[i - 1] = 0X
  132.  
  133.     RETURN res
  134. END PushStr;
  135.  
  136.  
  137. PROCEDURE GetStr* (list: BYTELIST; pos: INTEGER; VAR str: ARRAY OF CHAR): BOOLEAN;
  138. VAR
  139.     i:   INTEGER;
  140.     res: BOOLEAN;
  141.  
  142. BEGIN
  143.     res := FALSE;
  144.     i := 0;
  145.     WHILE (pos < list.length) & (i < LEN(str)) & ~res DO
  146.         str[i] := CHR(GetByte(list, pos));
  147.         res := str[i] = 0X;
  148.         INC(pos);
  149.         INC(i)
  150.     END
  151.  
  152.     RETURN res
  153. END GetStr;
  154.  
  155.  
  156. PROCEDURE WriteToFile* (file: WR.FILE; list: BYTELIST);
  157. VAR
  158.     chunk: BYTECHUNK;
  159.  
  160. BEGIN
  161.     chunk := list.first(BYTECHUNK);
  162.     WHILE chunk # NIL DO
  163.         WR.Write(file, chunk.data, chunk.count);
  164.         chunk := chunk.next(BYTECHUNK)
  165.     END
  166. END WriteToFile;
  167.  
  168.  
  169. PROCEDURE CreateByteList* (): BYTELIST;
  170. VAR
  171.     bytelist: BYTELIST;
  172.     list:     LISTS.LIST;
  173.     chunk:    BYTECHUNK;
  174.  
  175. BEGIN
  176.     NEW(bytelist);
  177.     list := LISTS.create(bytelist);
  178.     bytelist.length := 0;
  179.  
  180.     NEW(chunk);
  181.     chunk.count := 0;
  182.     LISTS.push(list, chunk)
  183.  
  184.     RETURN list(BYTELIST)
  185. END CreateByteList;
  186.  
  187.  
  188. PROCEDURE SetInt* (list: INTLIST; idx: INTEGER; int: INTEGER);
  189. VAR
  190.     ChunkNum: INTEGER;
  191.     chunk:    INTCHUNK;
  192.  
  193. BEGIN
  194.     ASSERT(idx >= 0);
  195.     ASSERT(list # NIL);
  196.  
  197.     ChunkNum := idx DIV LENOFINTCHUNK;
  198.     idx      := idx MOD LENOFINTCHUNK;
  199.  
  200.     chunk := list.first(INTCHUNK);
  201.  
  202.     WHILE (chunk # NIL) & (ChunkNum > 0) DO
  203.         chunk := chunk.next(INTCHUNK);
  204.         DEC(ChunkNum)
  205.     END;
  206.  
  207.     ASSERT(chunk # NIL);
  208.     ASSERT(idx < chunk.count);
  209.  
  210.     chunk.data[idx] := int
  211. END SetInt;
  212.  
  213.  
  214. PROCEDURE GetInt* (list: INTLIST; idx: INTEGER): INTEGER;
  215. VAR
  216.     ChunkNum: INTEGER;
  217.     chunk:    INTCHUNK;
  218.  
  219. BEGIN
  220.     ASSERT(idx >= 0);
  221.     ASSERT(list # NIL);
  222.  
  223.     ChunkNum := idx DIV LENOFINTCHUNK;
  224.     idx      := idx MOD LENOFINTCHUNK;
  225.  
  226.     chunk := list.first(INTCHUNK);
  227.  
  228.     WHILE (chunk # NIL) & (ChunkNum > 0) DO
  229.         chunk := chunk.next(INTCHUNK);
  230.         DEC(ChunkNum)
  231.     END;
  232.  
  233.     ASSERT(chunk # NIL);
  234.     ASSERT(idx < chunk.count)
  235.  
  236.     RETURN chunk.data[idx]
  237. END GetInt;
  238.  
  239.  
  240. PROCEDURE PushInt* (list: INTLIST; int: INTEGER);
  241. VAR
  242.     chunk: INTCHUNK;
  243.  
  244. BEGIN
  245.     ASSERT(list # NIL);
  246.  
  247.     chunk := list.last(INTCHUNK);
  248.  
  249.     IF chunk.count = LENOFINTCHUNK THEN
  250.         NEW(chunk);
  251.         chunk.count := 0;
  252.         LISTS.push(list, chunk)
  253.     END;
  254.  
  255.     chunk.data[chunk.count] := int;
  256.     INC(chunk.count);
  257.  
  258.     INC(list.length)
  259. END PushInt;
  260.  
  261.  
  262. PROCEDURE CreateIntList* (): INTLIST;
  263. VAR
  264.     intlist:  INTLIST;
  265.     list:     LISTS.LIST;
  266.     chunk:    INTCHUNK;
  267.  
  268. BEGIN
  269.     NEW(intlist);
  270.     list := LISTS.create(intlist);
  271.     intlist.length := 0;
  272.  
  273.     NEW(chunk);
  274.     chunk.count := 0;
  275.     LISTS.push(list, chunk)
  276.  
  277.     RETURN list(INTLIST)
  278. END CreateIntList;
  279.  
  280.  
  281. PROCEDURE Length* (list: ANYLIST): INTEGER;
  282.     RETURN list.length
  283. END Length;
  284.  
  285.  
  286. END CHUNKLISTS.