Subversion Repositories Kolibri OS

Rev

Rev 7693 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
7696 akron1 1
(*
7597 akron1 2
    BSD 2-Clause License
3
 
7696 akron1 4
    Copyright (c) 2018-2019, Anton Krotov
7597 akron1 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
 
7693 akron1 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
 
7597 akron1 156
PROCEDURE WriteToFile* (file: WR.FILE; list: BYTELIST);
157
VAR
158
    chunk: BYTECHUNK;
159
 
7693 akron1 160
BEGIN
7597 akron1 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
 
7696 akron1 286
END CHUNKLISTS.