Subversion Repositories Kolibri OS

Rev

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

Rev 7693 Rev 7696
1
(*
1
(*
2
    BSD 2-Clause License
2
    BSD 2-Clause License
3
 
3
 
4
    Copyright (c) 2018, 2019, 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
 
120
 
121
PROCEDURE PushStr* (list: BYTELIST; str: ARRAY OF CHAR): INTEGER;
121
PROCEDURE PushStr* (list: BYTELIST; str: ARRAY OF CHAR): INTEGER;
122
VAR
122
VAR
123
    i, res: INTEGER;
123
    i, res: INTEGER;
124
 
124
 
125
BEGIN
125
BEGIN
126
    res := list.length;
126
    res := list.length;
127
    i := 0;
127
    i := 0;
128
    REPEAT
128
    REPEAT
129
        PushByte(list, ORD(str[i]));
129
        PushByte(list, ORD(str[i]));
130
        INC(i)
130
        INC(i)
131
    UNTIL str[i - 1] = 0X
131
    UNTIL str[i - 1] = 0X
132
 
132
 
133
    RETURN res
133
    RETURN res
134
END PushStr;
134
END PushStr;
135
 
135
 
136
 
136
 
137
PROCEDURE GetStr* (list: BYTELIST; pos: INTEGER; VAR str: ARRAY OF CHAR): BOOLEAN;
137
PROCEDURE GetStr* (list: BYTELIST; pos: INTEGER; VAR str: ARRAY OF CHAR): BOOLEAN;
138
VAR
138
VAR
139
    i:   INTEGER;
139
    i:   INTEGER;
140
    res: BOOLEAN;
140
    res: BOOLEAN;
141
 
141
 
142
BEGIN
142
BEGIN
143
    res := FALSE;
143
    res := FALSE;
144
    i := 0;
144
    i := 0;
145
    WHILE (pos < list.length) & (i < LEN(str)) & ~res DO
145
    WHILE (pos < list.length) & (i < LEN(str)) & ~res DO
146
        str[i] := CHR(GetByte(list, pos));
146
        str[i] := CHR(GetByte(list, pos));
147
        res := str[i] = 0X;
147
        res := str[i] = 0X;
148
        INC(pos);
148
        INC(pos);
149
        INC(i)
149
        INC(i)
150
    END
150
    END
151
 
151
 
152
    RETURN res
152
    RETURN res
153
END GetStr;
153
END GetStr;
154
 
154
 
155
 
155
 
156
PROCEDURE WriteToFile* (file: WR.FILE; list: BYTELIST);
156
PROCEDURE WriteToFile* (file: WR.FILE; list: BYTELIST);
157
VAR
157
VAR
158
    chunk: BYTECHUNK;
158
    chunk: BYTECHUNK;
159
 
159
 
160
BEGIN
160
BEGIN
161
    chunk := list.first(BYTECHUNK);
161
    chunk := list.first(BYTECHUNK);
162
    WHILE chunk # NIL DO
162
    WHILE chunk # NIL DO
163
        WR.Write(file, chunk.data, chunk.count);
163
        WR.Write(file, chunk.data, chunk.count);
164
        chunk := chunk.next(BYTECHUNK)
164
        chunk := chunk.next(BYTECHUNK)
165
    END
165
    END
166
END WriteToFile;
166
END WriteToFile;
167
 
167
 
168
 
168
 
169
PROCEDURE CreateByteList* (): BYTELIST;
169
PROCEDURE CreateByteList* (): BYTELIST;
170
VAR
170
VAR
171
    bytelist: BYTELIST;
171
    bytelist: BYTELIST;
172
    list:     LISTS.LIST;
172
    list:     LISTS.LIST;
173
    chunk:    BYTECHUNK;
173
    chunk:    BYTECHUNK;
174
 
174
 
175
BEGIN
175
BEGIN
176
    NEW(bytelist);
176
    NEW(bytelist);
177
    list := LISTS.create(bytelist);
177
    list := LISTS.create(bytelist);
178
    bytelist.length := 0;
178
    bytelist.length := 0;
179
 
179
 
180
    NEW(chunk);
180
    NEW(chunk);
181
    chunk.count := 0;
181
    chunk.count := 0;
182
    LISTS.push(list, chunk)
182
    LISTS.push(list, chunk)
183
 
183
 
184
    RETURN list(BYTELIST)
184
    RETURN list(BYTELIST)
185
END CreateByteList;
185
END CreateByteList;
186
 
186
 
187
 
187
 
188
PROCEDURE SetInt* (list: INTLIST; idx: INTEGER; int: INTEGER);
188
PROCEDURE SetInt* (list: INTLIST; idx: INTEGER; int: INTEGER);
189
VAR
189
VAR
190
    ChunkNum: INTEGER;
190
    ChunkNum: INTEGER;
191
    chunk:    INTCHUNK;
191
    chunk:    INTCHUNK;
192
 
192
 
193
BEGIN
193
BEGIN
194
    ASSERT(idx >= 0);
194
    ASSERT(idx >= 0);
195
    ASSERT(list # NIL);
195
    ASSERT(list # NIL);
196
 
196
 
197
    ChunkNum := idx DIV LENOFINTCHUNK;
197
    ChunkNum := idx DIV LENOFINTCHUNK;
198
    idx      := idx MOD LENOFINTCHUNK;
198
    idx      := idx MOD LENOFINTCHUNK;
199
 
199
 
200
    chunk := list.first(INTCHUNK);
200
    chunk := list.first(INTCHUNK);
201
 
201
 
202
    WHILE (chunk # NIL) & (ChunkNum > 0) DO
202
    WHILE (chunk # NIL) & (ChunkNum > 0) DO
203
        chunk := chunk.next(INTCHUNK);
203
        chunk := chunk.next(INTCHUNK);
204
        DEC(ChunkNum)
204
        DEC(ChunkNum)
205
    END;
205
    END;
206
 
206
 
207
    ASSERT(chunk # NIL);
207
    ASSERT(chunk # NIL);
208
    ASSERT(idx < chunk.count);
208
    ASSERT(idx < chunk.count);
209
 
209
 
210
    chunk.data[idx] := int
210
    chunk.data[idx] := int
211
END SetInt;
211
END SetInt;
212
 
212
 
213
 
213
 
214
PROCEDURE GetInt* (list: INTLIST; idx: INTEGER): INTEGER;
214
PROCEDURE GetInt* (list: INTLIST; idx: INTEGER): INTEGER;
215
VAR
215
VAR
216
    ChunkNum: INTEGER;
216
    ChunkNum: INTEGER;
217
    chunk:    INTCHUNK;
217
    chunk:    INTCHUNK;
218
 
218
 
219
BEGIN
219
BEGIN
220
    ASSERT(idx >= 0);
220
    ASSERT(idx >= 0);
221
    ASSERT(list # NIL);
221
    ASSERT(list # NIL);
222
 
222
 
223
    ChunkNum := idx DIV LENOFINTCHUNK;
223
    ChunkNum := idx DIV LENOFINTCHUNK;
224
    idx      := idx MOD LENOFINTCHUNK;
224
    idx      := idx MOD LENOFINTCHUNK;
225
 
225
 
226
    chunk := list.first(INTCHUNK);
226
    chunk := list.first(INTCHUNK);
227
 
227
 
228
    WHILE (chunk # NIL) & (ChunkNum > 0) DO
228
    WHILE (chunk # NIL) & (ChunkNum > 0) DO
229
        chunk := chunk.next(INTCHUNK);
229
        chunk := chunk.next(INTCHUNK);
230
        DEC(ChunkNum)
230
        DEC(ChunkNum)
231
    END;
231
    END;
232
 
232
 
233
    ASSERT(chunk # NIL);
233
    ASSERT(chunk # NIL);
234
    ASSERT(idx < chunk.count)
234
    ASSERT(idx < chunk.count)
235
 
235
 
236
    RETURN chunk.data[idx]
236
    RETURN chunk.data[idx]
237
END GetInt;
237
END GetInt;
238
 
238
 
239
 
239
 
240
PROCEDURE PushInt* (list: INTLIST; int: INTEGER);
240
PROCEDURE PushInt* (list: INTLIST; int: INTEGER);
241
VAR
241
VAR
242
    chunk: INTCHUNK;
242
    chunk: INTCHUNK;
243
 
243
 
244
BEGIN
244
BEGIN
245
    ASSERT(list # NIL);
245
    ASSERT(list # NIL);
246
 
246
 
247
    chunk := list.last(INTCHUNK);
247
    chunk := list.last(INTCHUNK);
248
 
248
 
249
    IF chunk.count = LENOFINTCHUNK THEN
249
    IF chunk.count = LENOFINTCHUNK THEN
250
        NEW(chunk);
250
        NEW(chunk);
251
        chunk.count := 0;
251
        chunk.count := 0;
252
        LISTS.push(list, chunk)
252
        LISTS.push(list, chunk)
253
    END;
253
    END;
254
 
254
 
255
    chunk.data[chunk.count] := int;
255
    chunk.data[chunk.count] := int;
256
    INC(chunk.count);
256
    INC(chunk.count);
257
 
257
 
258
    INC(list.length)
258
    INC(list.length)
259
END PushInt;
259
END PushInt;
260
 
260
 
261
 
261
 
262
PROCEDURE CreateIntList* (): INTLIST;
262
PROCEDURE CreateIntList* (): INTLIST;
263
VAR
263
VAR
264
    intlist:  INTLIST;
264
    intlist:  INTLIST;
265
    list:     LISTS.LIST;
265
    list:     LISTS.LIST;
266
    chunk:    INTCHUNK;
266
    chunk:    INTCHUNK;
267
 
267
 
268
BEGIN
268
BEGIN
269
    NEW(intlist);
269
    NEW(intlist);
270
    list := LISTS.create(intlist);
270
    list := LISTS.create(intlist);
271
    intlist.length := 0;
271
    intlist.length := 0;
272
 
272
 
273
    NEW(chunk);
273
    NEW(chunk);
274
    chunk.count := 0;
274
    chunk.count := 0;
275
    LISTS.push(list, chunk)
275
    LISTS.push(list, chunk)
276
 
276
 
277
    RETURN list(INTLIST)
277
    RETURN list(INTLIST)
278
END CreateIntList;
278
END CreateIntList;
279
 
279
 
280
 
280
 
281
PROCEDURE Length* (list: ANYLIST): INTEGER;
281
PROCEDURE Length* (list: ANYLIST): INTEGER;
282
    RETURN list.length
282
    RETURN list.length
283
END Length;
283
END Length;
284
 
284
 
285
 
285
 
286
END CHUNKLISTS.
286
END CHUNKLISTS.