forked from KolibriOS/kolibrios
251 lines
4.5 KiB
Plaintext
251 lines
4.5 KiB
Plaintext
|
(*
|
||
|
BSD 2-Clause License
|
||
|
|
||
|
Copyright (c) 2018, Anton Krotov
|
||
|
All rights reserved.
|
||
|
*)
|
||
|
|
||
|
MODULE CHUNKLISTS;
|
||
|
|
||
|
IMPORT LISTS, WR := WRITER;
|
||
|
|
||
|
|
||
|
CONST
|
||
|
|
||
|
LENOFBYTECHUNK = 64000;
|
||
|
LENOFINTCHUNK = 16000;
|
||
|
|
||
|
|
||
|
TYPE
|
||
|
|
||
|
ANYLIST = POINTER TO RECORD (LISTS.LIST)
|
||
|
|
||
|
length: INTEGER
|
||
|
|
||
|
END;
|
||
|
|
||
|
BYTELIST* = POINTER TO RECORD (ANYLIST) END;
|
||
|
|
||
|
BYTECHUNK = POINTER TO RECORD (LISTS.ITEM)
|
||
|
|
||
|
data: ARRAY LENOFBYTECHUNK OF BYTE;
|
||
|
count: INTEGER
|
||
|
|
||
|
END;
|
||
|
|
||
|
|
||
|
INTLIST* = POINTER TO RECORD (ANYLIST) END;
|
||
|
|
||
|
INTCHUNK = POINTER TO RECORD (LISTS.ITEM)
|
||
|
|
||
|
data: ARRAY LENOFINTCHUNK OF INTEGER;
|
||
|
count: INTEGER
|
||
|
|
||
|
END;
|
||
|
|
||
|
|
||
|
PROCEDURE SetByte* (list: BYTELIST; idx: INTEGER; byte: BYTE);
|
||
|
VAR
|
||
|
ChunkNum: INTEGER;
|
||
|
chunk: BYTECHUNK;
|
||
|
|
||
|
BEGIN
|
||
|
ASSERT(idx >= 0);
|
||
|
ASSERT(list # NIL);
|
||
|
|
||
|
ChunkNum := idx DIV LENOFBYTECHUNK;
|
||
|
idx := idx MOD LENOFBYTECHUNK;
|
||
|
|
||
|
chunk := list.first(BYTECHUNK);
|
||
|
|
||
|
WHILE (chunk # NIL) & (ChunkNum > 0) DO
|
||
|
chunk := chunk.next(BYTECHUNK);
|
||
|
DEC(ChunkNum)
|
||
|
END;
|
||
|
|
||
|
ASSERT(chunk # NIL);
|
||
|
ASSERT(idx < chunk.count);
|
||
|
|
||
|
chunk.data[idx] := byte
|
||
|
END SetByte;
|
||
|
|
||
|
|
||
|
PROCEDURE GetByte* (list: BYTELIST; idx: INTEGER): BYTE;
|
||
|
VAR
|
||
|
ChunkNum: INTEGER;
|
||
|
chunk: BYTECHUNK;
|
||
|
|
||
|
BEGIN
|
||
|
ASSERT(idx >= 0);
|
||
|
ASSERT(list # NIL);
|
||
|
|
||
|
ChunkNum := idx DIV LENOFBYTECHUNK;
|
||
|
idx := idx MOD LENOFBYTECHUNK;
|
||
|
|
||
|
chunk := list.first(BYTECHUNK);
|
||
|
|
||
|
WHILE (chunk # NIL) & (ChunkNum > 0) DO
|
||
|
chunk := chunk.next(BYTECHUNK);
|
||
|
DEC(ChunkNum)
|
||
|
END;
|
||
|
|
||
|
ASSERT(chunk # NIL);
|
||
|
ASSERT(idx < chunk.count)
|
||
|
|
||
|
RETURN chunk.data[idx]
|
||
|
END GetByte;
|
||
|
|
||
|
|
||
|
PROCEDURE PushByte* (list: BYTELIST; byte: BYTE);
|
||
|
VAR
|
||
|
chunk: BYTECHUNK;
|
||
|
|
||
|
BEGIN
|
||
|
ASSERT(list # NIL);
|
||
|
|
||
|
chunk := list.last(BYTECHUNK);
|
||
|
|
||
|
IF chunk.count = LENOFBYTECHUNK THEN
|
||
|
NEW(chunk);
|
||
|
chunk.count := 0;
|
||
|
LISTS.push(list, chunk)
|
||
|
END;
|
||
|
|
||
|
chunk.data[chunk.count] := byte;
|
||
|
INC(chunk.count);
|
||
|
|
||
|
INC(list.length)
|
||
|
END PushByte;
|
||
|
|
||
|
|
||
|
PROCEDURE WriteToFile* (file: WR.FILE; list: BYTELIST);
|
||
|
VAR
|
||
|
chunk: BYTECHUNK;
|
||
|
|
||
|
BEGIN
|
||
|
chunk := list.first(BYTECHUNK);
|
||
|
WHILE chunk # NIL DO
|
||
|
WR.Write(file, chunk.data, chunk.count);
|
||
|
chunk := chunk.next(BYTECHUNK)
|
||
|
END
|
||
|
END WriteToFile;
|
||
|
|
||
|
|
||
|
PROCEDURE CreateByteList* (): BYTELIST;
|
||
|
VAR
|
||
|
bytelist: BYTELIST;
|
||
|
list: LISTS.LIST;
|
||
|
chunk: BYTECHUNK;
|
||
|
|
||
|
BEGIN
|
||
|
NEW(bytelist);
|
||
|
list := LISTS.create(bytelist);
|
||
|
bytelist.length := 0;
|
||
|
|
||
|
NEW(chunk);
|
||
|
chunk.count := 0;
|
||
|
LISTS.push(list, chunk)
|
||
|
|
||
|
RETURN list(BYTELIST)
|
||
|
END CreateByteList;
|
||
|
|
||
|
|
||
|
PROCEDURE SetInt* (list: INTLIST; idx: INTEGER; int: INTEGER);
|
||
|
VAR
|
||
|
ChunkNum: INTEGER;
|
||
|
chunk: INTCHUNK;
|
||
|
|
||
|
BEGIN
|
||
|
ASSERT(idx >= 0);
|
||
|
ASSERT(list # NIL);
|
||
|
|
||
|
ChunkNum := idx DIV LENOFINTCHUNK;
|
||
|
idx := idx MOD LENOFINTCHUNK;
|
||
|
|
||
|
chunk := list.first(INTCHUNK);
|
||
|
|
||
|
WHILE (chunk # NIL) & (ChunkNum > 0) DO
|
||
|
chunk := chunk.next(INTCHUNK);
|
||
|
DEC(ChunkNum)
|
||
|
END;
|
||
|
|
||
|
ASSERT(chunk # NIL);
|
||
|
ASSERT(idx < chunk.count);
|
||
|
|
||
|
chunk.data[idx] := int
|
||
|
END SetInt;
|
||
|
|
||
|
|
||
|
PROCEDURE GetInt* (list: INTLIST; idx: INTEGER): INTEGER;
|
||
|
VAR
|
||
|
ChunkNum: INTEGER;
|
||
|
chunk: INTCHUNK;
|
||
|
|
||
|
BEGIN
|
||
|
ASSERT(idx >= 0);
|
||
|
ASSERT(list # NIL);
|
||
|
|
||
|
ChunkNum := idx DIV LENOFINTCHUNK;
|
||
|
idx := idx MOD LENOFINTCHUNK;
|
||
|
|
||
|
chunk := list.first(INTCHUNK);
|
||
|
|
||
|
WHILE (chunk # NIL) & (ChunkNum > 0) DO
|
||
|
chunk := chunk.next(INTCHUNK);
|
||
|
DEC(ChunkNum)
|
||
|
END;
|
||
|
|
||
|
ASSERT(chunk # NIL);
|
||
|
ASSERT(idx < chunk.count)
|
||
|
|
||
|
RETURN chunk.data[idx]
|
||
|
END GetInt;
|
||
|
|
||
|
|
||
|
PROCEDURE PushInt* (list: INTLIST; int: INTEGER);
|
||
|
VAR
|
||
|
chunk: INTCHUNK;
|
||
|
|
||
|
BEGIN
|
||
|
ASSERT(list # NIL);
|
||
|
|
||
|
chunk := list.last(INTCHUNK);
|
||
|
|
||
|
IF chunk.count = LENOFINTCHUNK THEN
|
||
|
NEW(chunk);
|
||
|
chunk.count := 0;
|
||
|
LISTS.push(list, chunk)
|
||
|
END;
|
||
|
|
||
|
chunk.data[chunk.count] := int;
|
||
|
INC(chunk.count);
|
||
|
|
||
|
INC(list.length)
|
||
|
END PushInt;
|
||
|
|
||
|
|
||
|
PROCEDURE CreateIntList* (): INTLIST;
|
||
|
VAR
|
||
|
intlist: INTLIST;
|
||
|
list: LISTS.LIST;
|
||
|
chunk: INTCHUNK;
|
||
|
|
||
|
BEGIN
|
||
|
NEW(intlist);
|
||
|
list := LISTS.create(intlist);
|
||
|
intlist.length := 0;
|
||
|
|
||
|
NEW(chunk);
|
||
|
chunk.count := 0;
|
||
|
LISTS.push(list, chunk)
|
||
|
|
||
|
RETURN list(INTLIST)
|
||
|
END CreateIntList;
|
||
|
|
||
|
|
||
|
PROCEDURE Length* (list: ANYLIST): INTEGER;
|
||
|
RETURN list.length
|
||
|
END Length;
|
||
|
|
||
|
|
||
|
END CHUNKLISTS.
|