kolibrios-fun/programs/develop/oberon07/source/CHUNKLISTS.ob07

255 lines
4.6 KiB
Plaintext
Raw Normal View History

(*
BSD 2-Clause License
Copyright (c) 2018-2021, Anton Krotov
All rights reserved.
*)
MODULE CHUNKLISTS;
IMPORT LISTS, WR := WRITER;
CONST
LENOFBYTECHUNK = 65536;
LENOFINTCHUNK = 16384;
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
chunk: BYTECHUNK;
item: LISTS.ITEM;
BEGIN
ASSERT(idx >= 0);
ASSERT(list # NIL);
item := LISTS.getidx(list, idx DIV LENOFBYTECHUNK);
ASSERT(item # NIL);
chunk := item(BYTECHUNK);
idx := idx MOD LENOFBYTECHUNK;
ASSERT(idx < chunk.count);
chunk.data[idx] := byte
END SetByte;
PROCEDURE GetByte* (list: BYTELIST; idx: INTEGER): BYTE;
VAR
chunk: BYTECHUNK;
item: LISTS.ITEM;
BEGIN
ASSERT(idx >= 0);
ASSERT(list # NIL);
item := LISTS.getidx(list, idx DIV LENOFBYTECHUNK);
ASSERT(item # NIL);
chunk := item(BYTECHUNK);
idx := idx MOD LENOFBYTECHUNK;
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 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;
PROCEDURE WriteToFile* (list: BYTELIST);
VAR
chunk: BYTECHUNK;
BEGIN
chunk := list.first(BYTECHUNK);
WHILE chunk # NIL DO
WR.Write(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
chunk: INTCHUNK;
item: LISTS.ITEM;
BEGIN
ASSERT(idx >= 0);
ASSERT(list # NIL);
item := LISTS.getidx(list, idx DIV LENOFINTCHUNK);
ASSERT(item # NIL);
chunk := item(INTCHUNK);
idx := idx MOD LENOFINTCHUNK;
ASSERT(idx < chunk.count);
chunk.data[idx] := int
END SetInt;
PROCEDURE GetInt* (list: INTLIST; idx: INTEGER): INTEGER;
VAR
chunk: INTCHUNK;
item: LISTS.ITEM;
BEGIN
ASSERT(idx >= 0);
ASSERT(list # NIL);
item := LISTS.getidx(list, idx DIV LENOFINTCHUNK);
ASSERT(item # NIL);
chunk := item(INTCHUNK);
idx := idx MOD LENOFINTCHUNK;
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.