Subversion Repositories Kolibri OS

Rev

Rev 7597 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 7597 Rev 7693
1
(*
1
(*
2
    BSD 2-Clause License
2
    BSD 2-Clause License
3
 
3
 
4
    Copyright (c) 2018, Anton Krotov
4
    Copyright (c) 2018, 2019, Anton Krotov
5
    All rights reserved.
5
    All rights reserved.
6
*)
6
*)
7
 
7
 
8
MODULE CHUNKLISTS;
8
MODULE CHUNKLISTS;
9
 
9
 
10
IMPORT LISTS, WR := WRITER;
10
IMPORT LISTS, WR := WRITER;
11
 
11
 
12
 
12
 
13
CONST
13
CONST
14
 
14
 
15
    LENOFBYTECHUNK = 64000;
15
    LENOFBYTECHUNK = 64000;
16
    LENOFINTCHUNK  = 16000;
16
    LENOFINTCHUNK  = 16000;
17
 
17
 
18
 
18
 
19
TYPE
19
TYPE
20
 
20
 
21
    ANYLIST = POINTER TO RECORD (LISTS.LIST)
21
    ANYLIST = POINTER TO RECORD (LISTS.LIST)
22
 
22
 
23
        length: INTEGER
23
        length: INTEGER
24
 
24
 
25
    END;
25
    END;
26
 
26
 
27
    BYTELIST* = POINTER TO RECORD (ANYLIST) END;
27
    BYTELIST* = POINTER TO RECORD (ANYLIST) END;
28
 
28
 
29
    BYTECHUNK = POINTER TO RECORD (LISTS.ITEM)
29
    BYTECHUNK = POINTER TO RECORD (LISTS.ITEM)
30
 
30
 
31
        data:   ARRAY LENOFBYTECHUNK OF BYTE;
31
        data:   ARRAY LENOFBYTECHUNK OF BYTE;
32
        count:  INTEGER
32
        count:  INTEGER
33
 
33
 
34
    END;
34
    END;
35
 
35
 
36
 
36
 
37
    INTLIST* = POINTER TO RECORD (ANYLIST) END;
37
    INTLIST* = POINTER TO RECORD (ANYLIST) END;
38
 
38
 
39
    INTCHUNK = POINTER TO RECORD (LISTS.ITEM)
39
    INTCHUNK = POINTER TO RECORD (LISTS.ITEM)
40
 
40
 
41
        data:   ARRAY LENOFINTCHUNK OF INTEGER;
41
        data:   ARRAY LENOFINTCHUNK OF INTEGER;
42
        count:  INTEGER
42
        count:  INTEGER
43
 
43
 
44
    END;
44
    END;
45
 
45
 
46
 
46
 
47
PROCEDURE SetByte* (list: BYTELIST; idx: INTEGER; byte: BYTE);
47
PROCEDURE SetByte* (list: BYTELIST; idx: INTEGER; byte: BYTE);
48
VAR
48
VAR
49
    ChunkNum: INTEGER;
49
    ChunkNum: INTEGER;
50
    chunk:    BYTECHUNK;
50
    chunk:    BYTECHUNK;
51
 
51
 
52
BEGIN
52
BEGIN
53
    ASSERT(idx >= 0);
53
    ASSERT(idx >= 0);
54
    ASSERT(list # NIL);
54
    ASSERT(list # NIL);
55
 
55
 
56
    ChunkNum := idx DIV LENOFBYTECHUNK;
56
    ChunkNum := idx DIV LENOFBYTECHUNK;
57
    idx      := idx MOD LENOFBYTECHUNK;
57
    idx      := idx MOD LENOFBYTECHUNK;
58
 
58
 
59
    chunk := list.first(BYTECHUNK);
59
    chunk := list.first(BYTECHUNK);
60
 
60
 
61
    WHILE (chunk # NIL) & (ChunkNum > 0) DO
61
    WHILE (chunk # NIL) & (ChunkNum > 0) DO
62
        chunk := chunk.next(BYTECHUNK);
62
        chunk := chunk.next(BYTECHUNK);
63
        DEC(ChunkNum)
63
        DEC(ChunkNum)
64
    END;
64
    END;
65
 
65
 
66
    ASSERT(chunk # NIL);
66
    ASSERT(chunk # NIL);
67
    ASSERT(idx < chunk.count);
67
    ASSERT(idx < chunk.count);
68
 
68
 
69
    chunk.data[idx] := byte
69
    chunk.data[idx] := byte
70
END SetByte;
70
END SetByte;
71
 
71
 
72
 
72
 
73
PROCEDURE GetByte* (list: BYTELIST; idx: INTEGER): BYTE;
73
PROCEDURE GetByte* (list: BYTELIST; idx: INTEGER): BYTE;
74
VAR
74
VAR
75
    ChunkNum: INTEGER;
75
    ChunkNum: INTEGER;
76
    chunk:    BYTECHUNK;
76
    chunk:    BYTECHUNK;
77
 
77
 
78
BEGIN
78
BEGIN
79
    ASSERT(idx >= 0);
79
    ASSERT(idx >= 0);
80
    ASSERT(list # NIL);
80
    ASSERT(list # NIL);
81
 
81
 
82
    ChunkNum := idx DIV LENOFBYTECHUNK;
82
    ChunkNum := idx DIV LENOFBYTECHUNK;
83
    idx      := idx MOD LENOFBYTECHUNK;
83
    idx      := idx MOD LENOFBYTECHUNK;
84
 
84
 
85
    chunk := list.first(BYTECHUNK);
85
    chunk := list.first(BYTECHUNK);
86
 
86
 
87
    WHILE (chunk # NIL) & (ChunkNum > 0) DO
87
    WHILE (chunk # NIL) & (ChunkNum > 0) DO
88
        chunk := chunk.next(BYTECHUNK);
88
        chunk := chunk.next(BYTECHUNK);
89
        DEC(ChunkNum)
89
        DEC(ChunkNum)
90
    END;
90
    END;
91
 
91
 
92
    ASSERT(chunk # NIL);
92
    ASSERT(chunk # NIL);
93
    ASSERT(idx < chunk.count)
93
    ASSERT(idx < chunk.count)
94
 
94
 
95
    RETURN chunk.data[idx]
95
    RETURN chunk.data[idx]
96
END GetByte;
96
END GetByte;
97
 
97
 
98
 
98
 
99
PROCEDURE PushByte* (list: BYTELIST; byte: BYTE);
99
PROCEDURE PushByte* (list: BYTELIST; byte: BYTE);
100
VAR
100
VAR
101
    chunk: BYTECHUNK;
101
    chunk: BYTECHUNK;
102
 
102
 
103
BEGIN
103
BEGIN
104
    ASSERT(list # NIL);
104
    ASSERT(list # NIL);
105
 
105
 
106
    chunk := list.last(BYTECHUNK);
106
    chunk := list.last(BYTECHUNK);
107
 
107
 
108
    IF chunk.count = LENOFBYTECHUNK THEN
108
    IF chunk.count = LENOFBYTECHUNK THEN
109
        NEW(chunk);
109
        NEW(chunk);
110
        chunk.count := 0;
110
        chunk.count := 0;
111
        LISTS.push(list, chunk)
111
        LISTS.push(list, chunk)
112
    END;
112
    END;
113
 
113
 
114
    chunk.data[chunk.count] := byte;
114
    chunk.data[chunk.count] := byte;
115
    INC(chunk.count);
115
    INC(chunk.count);
116
 
116
 
117
    INC(list.length)
117
    INC(list.length)
118
END PushByte;
118
END PushByte;
119
 
119
 
-
 
120
 
-
 
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
 
120
 
155
 
121
PROCEDURE WriteToFile* (file: WR.FILE; list: BYTELIST);
156
PROCEDURE WriteToFile* (file: WR.FILE; list: BYTELIST);
122
VAR
157
VAR
123
    chunk: BYTECHUNK;
158
    chunk: BYTECHUNK;
124
 
159
 
125
BEGIN              
160
BEGIN
126
    chunk := list.first(BYTECHUNK);
161
    chunk := list.first(BYTECHUNK);
127
    WHILE chunk # NIL DO
162
    WHILE chunk # NIL DO
128
        WR.Write(file, chunk.data, chunk.count);
163
        WR.Write(file, chunk.data, chunk.count);
129
        chunk := chunk.next(BYTECHUNK)
164
        chunk := chunk.next(BYTECHUNK)
130
    END
165
    END
131
END WriteToFile;
166
END WriteToFile;
132
 
167
 
133
 
168
 
134
PROCEDURE CreateByteList* (): BYTELIST;
169
PROCEDURE CreateByteList* (): BYTELIST;
135
VAR
170
VAR
136
    bytelist: BYTELIST;
171
    bytelist: BYTELIST;
137
    list:     LISTS.LIST;
172
    list:     LISTS.LIST;
138
    chunk:    BYTECHUNK;
173
    chunk:    BYTECHUNK;
139
 
174
 
140
BEGIN
175
BEGIN
141
    NEW(bytelist);
176
    NEW(bytelist);
142
    list := LISTS.create(bytelist);
177
    list := LISTS.create(bytelist);
143
    bytelist.length := 0;
178
    bytelist.length := 0;
144
 
179
 
145
    NEW(chunk);
180
    NEW(chunk);
146
    chunk.count := 0;
181
    chunk.count := 0;
147
    LISTS.push(list, chunk)
182
    LISTS.push(list, chunk)
148
 
183
 
149
    RETURN list(BYTELIST)
184
    RETURN list(BYTELIST)
150
END CreateByteList;
185
END CreateByteList;
151
 
186
 
152
 
187
 
153
PROCEDURE SetInt* (list: INTLIST; idx: INTEGER; int: INTEGER);
188
PROCEDURE SetInt* (list: INTLIST; idx: INTEGER; int: INTEGER);
154
VAR
189
VAR
155
    ChunkNum: INTEGER;
190
    ChunkNum: INTEGER;
156
    chunk:    INTCHUNK;
191
    chunk:    INTCHUNK;
157
 
192
 
158
BEGIN
193
BEGIN
159
    ASSERT(idx >= 0);
194
    ASSERT(idx >= 0);
160
    ASSERT(list # NIL);
195
    ASSERT(list # NIL);
161
 
196
 
162
    ChunkNum := idx DIV LENOFINTCHUNK;
197
    ChunkNum := idx DIV LENOFINTCHUNK;
163
    idx      := idx MOD LENOFINTCHUNK;
198
    idx      := idx MOD LENOFINTCHUNK;
164
 
199
 
165
    chunk := list.first(INTCHUNK);
200
    chunk := list.first(INTCHUNK);
166
 
201
 
167
    WHILE (chunk # NIL) & (ChunkNum > 0) DO
202
    WHILE (chunk # NIL) & (ChunkNum > 0) DO
168
        chunk := chunk.next(INTCHUNK);
203
        chunk := chunk.next(INTCHUNK);
169
        DEC(ChunkNum)
204
        DEC(ChunkNum)
170
    END;
205
    END;
171
 
206
 
172
    ASSERT(chunk # NIL);
207
    ASSERT(chunk # NIL);
173
    ASSERT(idx < chunk.count);
208
    ASSERT(idx < chunk.count);
174
 
209
 
175
    chunk.data[idx] := int
210
    chunk.data[idx] := int
176
END SetInt;
211
END SetInt;
177
 
212
 
178
 
213
 
179
PROCEDURE GetInt* (list: INTLIST; idx: INTEGER): INTEGER;
214
PROCEDURE GetInt* (list: INTLIST; idx: INTEGER): INTEGER;
180
VAR
215
VAR
181
    ChunkNum: INTEGER;
216
    ChunkNum: INTEGER;
182
    chunk:    INTCHUNK;
217
    chunk:    INTCHUNK;
183
 
218
 
184
BEGIN
219
BEGIN
185
    ASSERT(idx >= 0);
220
    ASSERT(idx >= 0);
186
    ASSERT(list # NIL);
221
    ASSERT(list # NIL);
187
 
222
 
188
    ChunkNum := idx DIV LENOFINTCHUNK;
223
    ChunkNum := idx DIV LENOFINTCHUNK;
189
    idx      := idx MOD LENOFINTCHUNK;
224
    idx      := idx MOD LENOFINTCHUNK;
190
 
225
 
191
    chunk := list.first(INTCHUNK);
226
    chunk := list.first(INTCHUNK);
192
 
227
 
193
    WHILE (chunk # NIL) & (ChunkNum > 0) DO
228
    WHILE (chunk # NIL) & (ChunkNum > 0) DO
194
        chunk := chunk.next(INTCHUNK);
229
        chunk := chunk.next(INTCHUNK);
195
        DEC(ChunkNum)
230
        DEC(ChunkNum)
196
    END;
231
    END;
197
 
232
 
198
    ASSERT(chunk # NIL);
233
    ASSERT(chunk # NIL);
199
    ASSERT(idx < chunk.count)
234
    ASSERT(idx < chunk.count)
200
 
235
 
201
    RETURN chunk.data[idx]
236
    RETURN chunk.data[idx]
202
END GetInt;
237
END GetInt;
203
 
238
 
204
 
239
 
205
PROCEDURE PushInt* (list: INTLIST; int: INTEGER);
240
PROCEDURE PushInt* (list: INTLIST; int: INTEGER);
206
VAR
241
VAR
207
    chunk: INTCHUNK;
242
    chunk: INTCHUNK;
208
 
243
 
209
BEGIN
244
BEGIN
210
    ASSERT(list # NIL);
245
    ASSERT(list # NIL);
211
 
246
 
212
    chunk := list.last(INTCHUNK);
247
    chunk := list.last(INTCHUNK);
213
 
248
 
214
    IF chunk.count = LENOFINTCHUNK THEN
249
    IF chunk.count = LENOFINTCHUNK THEN
215
        NEW(chunk);
250
        NEW(chunk);
216
        chunk.count := 0;
251
        chunk.count := 0;
217
        LISTS.push(list, chunk)
252
        LISTS.push(list, chunk)
218
    END;
253
    END;
219
 
254
 
220
    chunk.data[chunk.count] := int;
255
    chunk.data[chunk.count] := int;
221
    INC(chunk.count);
256
    INC(chunk.count);
222
 
257
 
223
    INC(list.length)
258
    INC(list.length)
224
END PushInt;
259
END PushInt;
225
 
260
 
226
 
261
 
227
PROCEDURE CreateIntList* (): INTLIST;
262
PROCEDURE CreateIntList* (): INTLIST;
228
VAR
263
VAR
229
    intlist:  INTLIST;
264
    intlist:  INTLIST;
230
    list:     LISTS.LIST;
265
    list:     LISTS.LIST;
231
    chunk:    INTCHUNK;
266
    chunk:    INTCHUNK;
232
 
267
 
233
BEGIN
268
BEGIN
234
    NEW(intlist);
269
    NEW(intlist);
235
    list := LISTS.create(intlist);
270
    list := LISTS.create(intlist);
236
    intlist.length := 0;
271
    intlist.length := 0;
237
 
272
 
238
    NEW(chunk);
273
    NEW(chunk);
239
    chunk.count := 0;
274
    chunk.count := 0;
240
    LISTS.push(list, chunk)
275
    LISTS.push(list, chunk)
241
 
276
 
242
    RETURN list(INTLIST)
277
    RETURN list(INTLIST)
243
END CreateIntList;
278
END CreateIntList;
244
 
279
 
245
 
280
 
246
PROCEDURE Length* (list: ANYLIST): INTEGER;
281
PROCEDURE Length* (list: ANYLIST): INTEGER;
247
    RETURN list.length
282
    RETURN list.length
248
END Length;
283
END Length;
249
 
284
 
250
 
285
 
251
END CHUNKLISTS.
286
END CHUNKLISTS.