Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
7597 akron1 1
(*
2
    BSD 2-Clause License
3
 
4
    Copyright (c) 2018, 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 WriteToFile* (file: WR.FILE; list: BYTELIST);
122
VAR
123
    chunk: BYTECHUNK;
124
 
125
BEGIN
126
    chunk := list.first(BYTECHUNK);
127
    WHILE chunk # NIL DO
128
        WR.Write(file, chunk.data, chunk.count);
129
        chunk := chunk.next(BYTECHUNK)
130
    END
131
END WriteToFile;
132
 
133
 
134
PROCEDURE CreateByteList* (): BYTELIST;
135
VAR
136
    bytelist: BYTELIST;
137
    list:     LISTS.LIST;
138
    chunk:    BYTECHUNK;
139
 
140
BEGIN
141
    NEW(bytelist);
142
    list := LISTS.create(bytelist);
143
    bytelist.length := 0;
144
 
145
    NEW(chunk);
146
    chunk.count := 0;
147
    LISTS.push(list, chunk)
148
 
149
    RETURN list(BYTELIST)
150
END CreateByteList;
151
 
152
 
153
PROCEDURE SetInt* (list: INTLIST; idx: INTEGER; int: INTEGER);
154
VAR
155
    ChunkNum: INTEGER;
156
    chunk:    INTCHUNK;
157
 
158
BEGIN
159
    ASSERT(idx >= 0);
160
    ASSERT(list # NIL);
161
 
162
    ChunkNum := idx DIV LENOFINTCHUNK;
163
    idx      := idx MOD LENOFINTCHUNK;
164
 
165
    chunk := list.first(INTCHUNK);
166
 
167
    WHILE (chunk # NIL) & (ChunkNum > 0) DO
168
        chunk := chunk.next(INTCHUNK);
169
        DEC(ChunkNum)
170
    END;
171
 
172
    ASSERT(chunk # NIL);
173
    ASSERT(idx < chunk.count);
174
 
175
    chunk.data[idx] := int
176
END SetInt;
177
 
178
 
179
PROCEDURE GetInt* (list: INTLIST; idx: INTEGER): INTEGER;
180
VAR
181
    ChunkNum: INTEGER;
182
    chunk:    INTCHUNK;
183
 
184
BEGIN
185
    ASSERT(idx >= 0);
186
    ASSERT(list # NIL);
187
 
188
    ChunkNum := idx DIV LENOFINTCHUNK;
189
    idx      := idx MOD LENOFINTCHUNK;
190
 
191
    chunk := list.first(INTCHUNK);
192
 
193
    WHILE (chunk # NIL) & (ChunkNum > 0) DO
194
        chunk := chunk.next(INTCHUNK);
195
        DEC(ChunkNum)
196
    END;
197
 
198
    ASSERT(chunk # NIL);
199
    ASSERT(idx < chunk.count)
200
 
201
    RETURN chunk.data[idx]
202
END GetInt;
203
 
204
 
205
PROCEDURE PushInt* (list: INTLIST; int: INTEGER);
206
VAR
207
    chunk: INTCHUNK;
208
 
209
BEGIN
210
    ASSERT(list # NIL);
211
 
212
    chunk := list.last(INTCHUNK);
213
 
214
    IF chunk.count = LENOFINTCHUNK THEN
215
        NEW(chunk);
216
        chunk.count := 0;
217
        LISTS.push(list, chunk)
218
    END;
219
 
220
    chunk.data[chunk.count] := int;
221
    INC(chunk.count);
222
 
223
    INC(list.length)
224
END PushInt;
225
 
226
 
227
PROCEDURE CreateIntList* (): INTLIST;
228
VAR
229
    intlist:  INTLIST;
230
    list:     LISTS.LIST;
231
    chunk:    INTCHUNK;
232
 
233
BEGIN
234
    NEW(intlist);
235
    list := LISTS.create(intlist);
236
    intlist.length := 0;
237
 
238
    NEW(chunk);
239
    chunk.count := 0;
240
    LISTS.push(list, chunk)
241
 
242
    RETURN list(INTLIST)
243
END CreateIntList;
244
 
245
 
246
PROCEDURE Length* (list: ANYLIST): INTEGER;
247
    RETURN list.length
248
END Length;
249
 
250
 
251
END CHUNKLISTS.