14 years
edited 8 years
1 library ListT /* v1.0.1.0
2 ************************************************************************************3 *4 * */ uses /*
5 *6 * */ ErrorMessage /*
7 *8 ************************************************************************************9 *10 * module ListT11 *12 * Description13 * -------------------------14 *15 * NA16 *17 * Fields18 * -------------------------19 *20 * debug readonly boolean isList21 * debug readonly boolean isElement22 *23 * readonly static integer sentinel24 *25 * readonly thistype list26 *27 * readonly thistype first28 * readonly thistype last29 *30 * readonly thistype next31 * readonly thistype prev32 *33 * Methods34 * -------------------------35 *36 * static method create takes nothing returns thistype37 * method destroy takes nothing returns nothing38 * - May only destroy lists39 *40 * method push takes nothing returns thistype41 * method enqueue takes nothing returns thistype42 *43 * method pop takes nothing returns nothing44 * method dequeue takes nothing returns nothing45 *46 * method remove takes nothing returns nothing47 *48 * method clear takes nothing returns nothing49 *50 * debug static method calculateMemoryUsage takes nothing returns integer51 * debug static method getAllocatedMemoryAsString takes nothing returns string52 *53 ************************************************************************************/54 private keyword isNode
55 private keyword isCollection
56 private keyword pp_list
57 private keyword pp_next
58 private keyword pp_prev
59 private keyword pp_first
60 private keyword pp_last
61 62 module ListT63 private static thistype collectionCount = 0
64 private static thistype nodeCount = 0
65
66 debug private static Table p_isNode
67 debug method operator isNode takes nothing returns boolean
68 debug return p_isNode.boolean[this]
69 debug endmethod
70 debug method operator isNode= takes boolean value returns nothing
71 debug set p_isNode.boolean[this] = value
72 debug endmethod
73
74 debug private static Table p_isCollection
75 debug method operator isCollection takes nothing returns boolean
76 debug return p_isCollection.boolean[this]
77 debug endmethod
78 debug method operator isCollection= takes boolean value returns nothing
79 debug set p_isCollection.boolean[this] = value
80 debug endmethod
81
82 debug method operator isList takes nothing returns boolean
83 debug return isCollection
84 debug endmethod
85
86 debug method operator isElement takes nothing returns boolean
87 debug return isNode
88 debug endmethod
89
90 private static Table p_list
91 method operator pp_list takes nothing returns thistype
92 return p_list[this]
93 endmethod94 method operator pp_list= takes thistype value returns nothing
95 set p_list[this] = value
96 endmethod97 method operator list takes nothing returns thistype
98 debug call ThrowError(this == 0, "List", "list", "thistype", this, "Attempted To Read Null Node.")
99 debug call ThrowError(not isNode, "List", "list", "thistype", this, "Attempted To Read Invalid Node.")
100 return pp_list101 endmethod102
103 private static Table p_next
104 method operator pp_next takes nothing returns thistype
105 return p_next[this]
106 endmethod107 method operator pp_next= takes thistype value returns nothing
108 set p_next[this] = value
109 endmethod110 method operator next takes nothing returns thistype
111 debug call ThrowError(this == 0, "List", "next", "thistype", this, "Attempted To Go Out Of Bounds.")
112 debug call ThrowError(not isNode, "List", "next", "thistype", this, "Attempted To Read Invalid Node.")
113 return pp_next114 endmethod115
116 private static Table p_prev
117 method operator pp_prev takes nothing returns thistype
118 return p_prev[this]
119 endmethod120 method operator pp_prev= takes thistype value returns nothing
121 set p_prev[this] = value
122 endmethod123 method operator prev takes nothing returns thistype
124 debug call ThrowError(this == 0, "List", "prev", "thistype", this, "Attempted To Go Out Of Bounds.")
125 debug call ThrowError(not isNode, "List", "prev", "thistype", this, "Attempted To Read Invalid Node.")
126 return pp_prev127 endmethod128
129 private static Table p_first
130 method operator pp_first takes nothing returns thistype
131 return p_first[this]
132 endmethod133 method operator pp_first= takes thistype value returns nothing
134 set p_first[this] = value
135 endmethod136 method operator first takes nothing returns thistype
137 debug call ThrowError(this == 0, "List", "first", "thistype", this, "Attempted To Read Null List.")
138 debug call ThrowError(not isCollection, "List", "first", "thistype", this, "Attempted To Read Invalid List.")
139 return pp_first140 endmethod141
142 private static Table p_last
143 method operator pp_last takes nothing returns thistype
144 return p_last[this]
145 endmethod146 method operator pp_last= takes thistype value returns nothing
147 set p_last[this] = value
148 endmethod149 method operator last takes nothing returns thistype
150 debug call ThrowError(this == 0, "List", "last", "thistype", this, "Attempted To Read Null List.")
151 debug call ThrowError(not isCollection, "List", "last", "thistype", this, "Attempted To Read Invalid List.")
152 return pp_last153 endmethod154
155 static method operator sentinel takes nothing returns integer
156 return 0
157 endmethod158
159 private static method allocateCollection takes nothing returns thistype
160 local thistype this = thistype(0).pp_first
161
162 if (0 == this) then
163 debug call ThrowError(collectionCount == 8191, "List", "allocateCollection", "thistype", 0, "Overflow.")
164
165 set this = collectionCount + 1
166 set collectionCount = this
167 else168 set thistype(0).pp_first = pp_first
169 endif170
171 return this
172 endmethod173
174 private static method allocateNode takes nothing returns thistype
175 local thistype this = thistype(0).pp_next
176
177 if (0 == this) then
178 debug call ThrowError(nodeCount == 8191, "List", "allocateNode", "thistype", 0, "Overflow.")
179
180 set this = nodeCount + 1
181 set nodeCount = this
182 else183 set thistype(0).pp_next = pp_next
184 endif185
186 return this
187 endmethod188
189 static method create takes nothing returns thistype
190 local thistype this = allocateCollection()
191
192 debug set isCollection = true
193
194 set pp_first = 0
195
196 return this
197 endmethod198 method push takes nothing returns thistype
199 local thistype node = allocateNode()
200
201 debug call ThrowError(this == 0, "List", "push", "thistype", this, "Attempted To Push On To Null List.")
202 debug call ThrowError(not isCollection, "List", "push", "thistype", this, "Attempted To Push On To Invalid List.")
203
204 debug set node.isNode = true
205
206 set node.pp_list = this
207
208 if (pp_first == 0) then
209 set pp_first = node
210 set pp_last = node
211 set node.pp_next = 0
212 else213 set pp_first.pp_prev = node
214 set node.pp_next = pp_first
215 set pp_first = node
216 endif217
218 set node.pp_prev = 0
219
220 return node221 endmethod222 method enqueue takes nothing returns thistype
223 local thistype node = allocateNode()
224
225 debug call ThrowError(this == 0, "List", "enqueue", "thistype", this, "Attempted To Enqueue On To Null List.")
226 debug call ThrowError(not isCollection, "List", "enqueue", "thistype", this, "Attempted To Enqueue On To Invalid List.")
227
228 debug set node.isNode = true
229
230 set node.pp_list = this
231
232 if (pp_first == 0) then
233 set pp_first = node
234 set pp_last = node
235 set node.pp_prev = 0
236 else237 set pp_last.pp_next = node
238 set node.pp_prev = pp_last
239 set pp_last = node
240 endif241
242 set node.pp_next = 0
243
244 return node245 endmethod246 method pop takes nothing returns nothing
247 local thistype node = pp_first
248
249 debug call ThrowError(this == 0, "List", "pop", "thistype", this, "Attempted To Pop Null List.")
250 debug call ThrowError(not isCollection, "List", "pop", "thistype", this, "Attempted To Pop Invalid List.")
251 debug call ThrowError(node == 0, "List", "pop", "thistype", this, "Attempted To Pop Empty List.")
252
253 debug set node.isNode = false
254
255 set pp_first.pp_list = 0
256
257 set pp_first = pp_first.pp_next
258 if (pp_first == 0) then
259 set pp_last = 0
260 else261 set pp_first.pp_prev = 0
262 endif263
264 set node.pp_next = thistype(0).pp_next
265 set thistype(0).pp_next = node
266 endmethod267 method dequeue takes nothing returns nothing
268 local thistype node = pp_last
269
270 debug call ThrowError(this == 0, "List", "dequeue", "thistype", this, "Attempted To Dequeue Null List.")
271 debug call ThrowError(not isCollection, "List", "dequeue", "thistype", this, "Attempted To Dequeue Invalid List.")
272 debug call ThrowError(node == 0, "List", "dequeue", "thistype", this, "Attempted To Dequeue Empty List.")
273
274 debug set node.isNode = false
275
276 set pp_last.pp_list = 0
277
278 set pp_last = pp_last.pp_prev
279 if (pp_last == 0) then
280 set pp_first = 0
281 else282 set pp_last.pp_next = 0
283 endif284
285 set node.pp_next = thistype(0).pp_next
286 set thistype(0).pp_next = node
287 endmethod288 method remove takes nothing returns nothing
289 local thistype node = this
290 set this = node.pp_list
291
292 debug call ThrowError(node == 0, "List", "remove", "thistype", this, "Attempted To Remove Null Node.")
293 debug call ThrowError(not node.isNode, "List", "remove", "thistype", this, "Attempted To Remove Invalid Node (" + I2S(node) + ").")
294
295 debug set node.isNode = false
296
297 set node.pp_list = 0
298
299 if (0 == node.pp_prev) then
300 set pp_first = node.pp_next
301 else302 set node.pp_prev.pp_next = node.pp_next
303 endif304 if (0 == node.pp_next) then
305 set pp_last = node.pp_prev
306 else307 set node.pp_next.pp_prev = node.pp_prev
308 endif309
310 set node.pp_next = thistype(0).pp_next
311 set thistype(0).pp_next = node
312 endmethod313 method clear takes nothing returns nothing
314 debug local thistype node = pp_first
315
316 debug call ThrowError(this == 0, "List", "clear", "thistype", this, "Attempted To Clear Null List.")
317 debug call ThrowError(not isCollection, "List", "clear", "thistype", this, "Attempted To Clear Invalid List.")
318
319 static if DEBUG_MODE then
320 loop321 exitwhen node == 0
322 set node.isNode = false
323 set node = node.pp_next
324 endloop325 endif326
327 if (pp_first == 0) then
328 return329 endif330
331 set pp_last.pp_next = thistype(0).pp_next
332 set thistype(0).pp_next = pp_first
333
334 set pp_first = 0
335 set pp_last = 0
336 endmethod337 method destroy takes nothing returns nothing
338 debug call ThrowError(this == 0, "List", "destroy", "thistype", this, "Attempted To Destroy Null List.")
339 debug call ThrowError(not isCollection, "List", "destroy", "thistype", this, "Attempted To Destroy Invalid List.")
340
341 static if DEBUG_MODE then
342 debug call clear()
343
344 debug set isCollection = false
345 else346 if (pp_first != 0) then
347 set pp_last.pp_next = thistype(0).pp_next
348 set thistype(0).pp_next = pp_first
349
350 set pp_last = 0
351 endif352 endif353
354 set pp_first = thistype(0).pp_first
355 set thistype(0).pp_first = this
356 endmethod357
358 private static method onInit takes nothing returns nothing
359 static if DEBUG_MODE then
360 set p_isNode = Table.create()
361 set p_isCollection = Table.create()
362 endif363 set p_list = Table.create()
364 set p_next = Table.create()
365 set p_prev = Table.create()
366 set p_first = Table.create()
367 set p_last = Table.create()
368 endmethod369
370 static if DEBUG_MODE then
371 static method calculateMemoryUsage takes nothing returns integer
372 local thistype start = 1
373 local thistype end = 8191
374 local integer count = 0
375
376 loop377 exitwhen integer(start) > integer(end)
378 if (integer(start) + 500 > integer(end)) then
379 return count + checkRegion(start, end)
380 else381 set count = count + checkRegion(start, start + 500)
382 set start = start + 501
383 endif384 endloop385
386 return count387 endmethod388
389 private static method checkRegion takes thistype start, thistype end returns integer
390 local integer count = 0
391
392 loop393 exitwhen integer(start) > integer(end)
394 if (start.isNode) then
395 set count = count + 1
396 endif397 if (start.isCollection) then
398 set count = count + 1
399 endif400 set start = start + 1
401 endloop402
403 return count404 endmethod405
406 static method getAllocatedMemoryAsString takes nothing returns string
407 local thistype start = 1
408 local thistype end = 8191
409 local string memory = null
410
411 loop412 exitwhen integer(start) > integer(end)
413 if (integer(start) + 500 > integer(end)) then
414 if (memory != null) then
415 set memory = memory + ", "
416 endif417 set memory = memory + checkRegion2(start, end)
418 set start = end + 1
419 else420 if (memory != null) then
421 set memory = memory + ", "
422 endif423 set memory = memory + checkRegion2(start, start + 500)
424 set start = start + 501
425 endif426 endloop427
428 return memory429 endmethod430
431 private static method checkRegion2 takes thistype start, thistype end returns string
432 local string memory = null
433
434 loop435 exitwhen integer(start) > integer(end)
436 if (start.isNode) then
437 if (memory == null) then
438 set memory = I2S(start)
439 else440 set memory = memory + ", " + I2S(start) + "N"
441 endif442 endif443 if (start.isCollection) then
444 if (memory == null) then
445 set memory = I2S(start)
446 else447 set memory = memory + ", " + I2S(start) + "C"
448 endif449 endif450 set start = start + 1
451 endloop452
453 return memory454 endmethod455 endif456 endmodule457 endlibrary