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.>>>>>> |