2019-03-11 09:59:55 +01:00
|
|
|
(*
|
|
|
|
BSD 2-Clause License
|
|
|
|
|
2019-09-26 22:23:06 +02:00
|
|
|
Copyright (c) 2018, 2019, Anton Krotov
|
2019-03-11 09:59:55 +01:00
|
|
|
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;
|
|
|
|
|
|
|
|
|
2019-09-26 22:23:06 +02:00
|
|
|
PROCEDURE PushStr* (list: BYTELIST; str: ARRAY OF CHAR): INTEGER;
|
|
|
|
VAR
|
|
|
|
i, res: INTEGER;
|
|
|
|
|
|
|
|
BEGIN
|
|
|
|
res := list.length;
|
|
|
|
i := 0;
|
|
|
|
REPEAT
|
|
|
|
PushByte(list, ORD(str[i]));
|
|
|
|
INC(i)
|
|
|
|
UNTIL str[i - 1] = 0X
|
|
|
|
|
|
|
|
RETURN res
|
|
|
|
END PushStr;
|
|
|
|
|
|
|
|
|
|
|
|
PROCEDURE GetStr* (list: BYTELIST; pos: INTEGER; VAR str: ARRAY OF CHAR): BOOLEAN;
|
|
|
|
VAR
|
|
|
|
i: INTEGER;
|
|
|
|
res: BOOLEAN;
|
|
|
|
|
|
|
|
BEGIN
|
|
|
|
res := FALSE;
|
|
|
|
i := 0;
|
|
|
|
WHILE (pos < list.length) & (i < LEN(str)) & ~res DO
|
|
|
|
str[i] := CHR(GetByte(list, pos));
|
|
|
|
res := str[i] = 0X;
|
|
|
|
INC(pos);
|
|
|
|
INC(i)
|
|
|
|
END
|
|
|
|
|
|
|
|
RETURN res
|
|
|
|
END GetStr;
|
|
|
|
|
|
|
|
|
2019-03-11 09:59:55 +01:00
|
|
|
PROCEDURE WriteToFile* (file: WR.FILE; list: BYTELIST);
|
|
|
|
VAR
|
|
|
|
chunk: BYTECHUNK;
|
|
|
|
|
2019-09-26 22:23:06 +02:00
|
|
|
BEGIN
|
2019-03-11 09:59:55 +01:00
|
|
|
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.
|