ListT

Scripts

14 years
edited 8 years
Code (jass) Select
1
library ListT /* v1.0.1.0
2
************************************************************************************
3
*
4
*	*/ uses /*
5
*
6
*		*/ ErrorMessage	/*
7
*
8
************************************************************************************
9
*
10
*	module ListT
11
*
12
*		Description
13
*		-------------------------
14
*
15
*			NA
16
*
17
*		Fields
18
*		-------------------------
19
*
20
*			debug readonly boolean isList
21
*			debug readonly boolean isElement
22
*
23
*			readonly static integer sentinel
24
*
25
*			readonly thistype list
26
*
27
*			readonly thistype first
28
*			readonly thistype last
29
*
30
*			readonly thistype next
31
*			readonly thistype prev
32
*
33
*		Methods
34
*		-------------------------
35
*
36
*			static method create takes nothing returns thistype
37
*			method destroy takes nothing returns nothing
38
*				-	May only destroy lists
39
*
40
*			method push takes nothing returns thistype
41
*			method enqueue takes nothing returns thistype
42
*
43
*			method pop takes nothing returns nothing
44
*			method dequeue takes nothing returns nothing
45
*
46
*			method remove takes nothing returns nothing
47
*
48
*			method clear takes nothing returns nothing
49
*
50
*			debug static method calculateMemoryUsage takes nothing returns integer
51
*			debug static method getAllocatedMemoryAsString takes nothing returns string
52
*
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 ListT
63
		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
		endmethod
94
		method operator pp_list= takes thistype value returns nothing
95
			set p_list[this] = value
96
		endmethod
97
		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_list
101
		endmethod
102
		
103
		private static Table p_next
104
		method operator pp_next takes nothing returns thistype
105
			return p_next[this]
106
		endmethod
107
		method operator pp_next= takes thistype value returns nothing
108
			set p_next[this] = value
109
		endmethod
110
		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_next
114
		endmethod
115
		
116
		private static Table p_prev
117
		method operator pp_prev takes nothing returns thistype
118
			return p_prev[this]
119
		endmethod
120
		method operator pp_prev= takes thistype value returns nothing
121
			set p_prev[this] = value
122
		endmethod
123
		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_prev
127
		endmethod
128
		
129
		private static Table p_first
130
		method operator pp_first takes nothing returns thistype
131
			return p_first[this]
132
		endmethod
133
		method operator pp_first= takes thistype value returns nothing
134
			set p_first[this] = value
135
		endmethod
136
		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_first
140
		endmethod
141
		
142
		private static Table p_last
143
		method operator pp_last takes nothing returns thistype
144
			return p_last[this]
145
		endmethod
146
		method operator pp_last= takes thistype value returns nothing
147
			set p_last[this] = value
148
		endmethod
149
		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_last
153
		endmethod
154
		
155
		static method operator sentinel takes nothing returns integer
156
			return 0
157
		endmethod
158
		
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
			else
168
				set thistype(0).pp_first = pp_first
169
			endif
170
			
171
			return this
172
		endmethod
173
		
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
			else
183
				set thistype(0).pp_next = pp_next
184
			endif
185
			
186
			return this
187
		endmethod
188
		
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
		endmethod
198
		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
			else
213
				set pp_first.pp_prev = node
214
				set node.pp_next = pp_first
215
				set pp_first = node
216
			endif
217
			
218
			set node.pp_prev = 0
219
			
220
			return node
221
		endmethod
222
		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
			else
237
				set pp_last.pp_next = node
238
				set node.pp_prev = pp_last
239
				set pp_last = node
240
			endif
241
			
242
			set node.pp_next = 0
243
			
244
			return node
245
		endmethod
246
		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
			else
261
				set pp_first.pp_prev = 0
262
			endif
263
			
264
			set node.pp_next = thistype(0).pp_next
265
			set thistype(0).pp_next = node
266
		endmethod
267
		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
			else
282
				set pp_last.pp_next = 0
283
			endif
284
			
285
			set node.pp_next = thistype(0).pp_next
286
			set thistype(0).pp_next = node
287
		endmethod
288
		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
			else
302
				set node.pp_prev.pp_next = node.pp_next
303
			endif
304
			if (0 == node.pp_next) then
305
				set pp_last = node.pp_prev
306
			else
307
				set node.pp_next.pp_prev = node.pp_prev
308
			endif
309
			
310
			set node.pp_next = thistype(0).pp_next
311
			set thistype(0).pp_next = node
312
		endmethod
313
		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
				loop
321
					exitwhen node == 0
322
					set node.isNode = false
323
					set node = node.pp_next
324
				endloop
325
			endif
326
			
327
			if (pp_first == 0) then
328
				return
329
			endif
330
			
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
		endmethod
337
		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
			else
346
				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
				endif
352
			endif
353
			
354
			set pp_first = thistype(0).pp_first
355
			set thistype(0).pp_first = this
356
		endmethod
357
		
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
			endif
363
			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
		endmethod
369
		
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
				loop
377
					exitwhen integer(start) > integer(end)
378
					if (integer(start) + 500 > integer(end)) then
379
						return count + checkRegion(start, end)
380
					else
381
						set count = count + checkRegion(start, start + 500)
382
						set start = start + 501
383
					endif
384
				endloop
385
				
386
				return count
387
			endmethod
388
			
389
			private static method checkRegion takes thistype start, thistype end returns integer
390
				local integer count = 0
391
			
392
				loop
393
					exitwhen integer(start) > integer(end)
394
					if (start.isNode) then
395
						set count = count + 1
396
					endif
397
					if (start.isCollection) then
398
						set count = count + 1
399
					endif
400
					set start = start + 1
401
				endloop
402
				
403
				return count
404
			endmethod
405
			
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
				loop
412
					exitwhen integer(start) > integer(end)
413
					if (integer(start) + 500 > integer(end)) then
414
						if (memory != null) then
415
							set memory = memory + ", "
416
						endif
417
						set memory = memory + checkRegion2(start, end)
418
						set start = end + 1
419
					else
420
						if (memory != null) then
421
							set memory = memory + ", "
422
						endif
423
						set memory = memory + checkRegion2(start, start + 500)
424
						set start = start + 501
425
					endif
426
				endloop
427
				
428
				return memory
429
			endmethod
430
			
431
			private static method checkRegion2 takes thistype start, thistype end returns string
432
				local string memory = null
433
			
434
				loop
435
					exitwhen integer(start) > integer(end)
436
					if (start.isNode) then
437
						if (memory == null) then
438
							set memory = I2S(start)
439
						else
440
							set memory = memory + ", " + I2S(start) + "N"
441
						endif
442
					endif
443
					if (start.isCollection) then
444
						if (memory == null) then
445
							set memory = I2S(start)
446
						else
447
							set memory = memory + ", " + I2S(start) + "C"
448
						endif
449
					endif
450
					set start = start + 1
451
				endloop
452
				
453
				return memory
454
			endmethod
455
		endif
456
	endmodule
457
endlibrary