14 years
edited 8 years
Table is based on the philosophy that you can use one hashtable for your whole map. What it does is divide one hashtable into many different components, and each system in the map can have its own share of the hashtable. Taking advantage of parent keys and child keys to their fullest extent, the ability to have 1 hashtable for the whole map can now be realized.
I came up with the idea for this project after using Vexorian's Table and hitting the limits a number of times. All of those limitations have been fulfilled by this project:
You have access to all the hashtable API, so you can now save handles, booleans, reals, strings and integers, instead of just integers.
You can have up to 2 ^ 31 - 1 Table instances. Previously, you could have 400,000 if you set the constant appropriately, but that generates hundreds of lines of code. This means you don't ever have to worry about creating too many Tables, because you can never really have too many.
2-D array syntax is perfected and allows you to create things called TableArrays. The old method used the volatile StringHash, which easily bypasses the integer limit and starts saving into unpredictable places. This is dangerous when using a shared hashtable because you could overwrite someone else's data without even knowing it.
Table instances can save/load data from within module initializers. This didn't work before because the hashtable was initialized from a struct instead of from the globals block.
You can only have 256 hashtables at a time, so with 2 ^ 31 - 1 Table instances at your disposal and (that's right, I said "and", not "or") roughly 2 ^ 18 TableArray instances with array size 8192 (JASS max array size), you will find yourself with more storage options than you know what to do with.
If you take advantage of this system to its fullest, you will never need to call InitHashtable() again.
The basis of how it works is this: you often run into situations where you have no use for two keys (only a single key). Usually you just waste a key as 0 and run everything else through child-keys. This system (as well as Vexorian's Table) simply gives you a parent-key to use in a globally-shared hashtable. Just initialize an Table instance via Table.create().
But sometimes you need more than that, and both keys actually mean something to you. Usually the parent-key would be "this" from a struct and the child-keys are various other bits. A TableArray - an array of Tables - is a great way to achieve this. Instanciate a TableArray via TableArray[16] for an array of Tables sized 16, or TableArray[0x2000] for an array of Tables with the same size as a normal JASS array. The size can be very large if you want, but to be practical keep it smaller than a few million, because the total accumulated size of all your TableArrays must remain under 2 ** 31 - 1 (a little more than 2 billion) because that's the limit of how high integers can go.
If you're dealing with more randomly-accessed numbers or consistently very large indices in the parent-key field and couldn't previously accomplish it with a pre-sized TableArray, I have (on July 21, 2015) updated this to NewTable 4.0 where you can instantiate HashTables to do just that!
I now imagine this a completed project, so please let me know if there's more you'd like to see in the future and I'll take it into consideration.
Note the power of TableArray, how it splices the one hashtable into a many-dimensional array. This means you can have a multi-dimensional array (and more) per system.
I came up with the idea for this project after using Vexorian's Table and hitting the limits a number of times. All of those limitations have been fulfilled by this project:
You have access to all the hashtable API, so you can now save handles, booleans, reals, strings and integers, instead of just integers.
You can have up to 2 ^ 31 - 1 Table instances. Previously, you could have 400,000 if you set the constant appropriately, but that generates hundreds of lines of code. This means you don't ever have to worry about creating too many Tables, because you can never really have too many.
2-D array syntax is perfected and allows you to create things called TableArrays. The old method used the volatile StringHash, which easily bypasses the integer limit and starts saving into unpredictable places. This is dangerous when using a shared hashtable because you could overwrite someone else's data without even knowing it.
Table instances can save/load data from within module initializers. This didn't work before because the hashtable was initialized from a struct instead of from the globals block.
You can only have 256 hashtables at a time, so with 2 ^ 31 - 1 Table instances at your disposal and (that's right, I said "and", not "or") roughly 2 ^ 18 TableArray instances with array size 8192 (JASS max array size), you will find yourself with more storage options than you know what to do with.
If you take advantage of this system to its fullest, you will never need to call InitHashtable() again.
How it works
The basis of how it works is this: you often run into situations where you have no use for two keys (only a single key). Usually you just waste a key as 0 and run everything else through child-keys. This system (as well as Vexorian's Table) simply gives you a parent-key to use in a globally-shared hashtable. Just initialize an Table instance via Table.create().
But sometimes you need more than that, and both keys actually mean something to you. Usually the parent-key would be "this" from a struct and the child-keys are various other bits. A TableArray - an array of Tables - is a great way to achieve this. Instanciate a TableArray via TableArray[16] for an array of Tables sized 16, or TableArray[0x2000] for an array of Tables with the same size as a normal JASS array. The size can be very large if you want, but to be practical keep it smaller than a few million, because the total accumulated size of all your TableArrays must remain under 2 ** 31 - 1 (a little more than 2 billion) because that's the limit of how high integers can go.
If you're dealing with more randomly-accessed numbers or consistently very large indices in the parent-key field and couldn't previously accomplish it with a pre-sized TableArray, I have (on July 21, 2015) updated this to NewTable 4.0 where you can instantiate HashTables to do just that!
I now imagine this a completed project, so please let me know if there's more you'd like to see in the future and I'll take it into consideration.
1 2 library Table /* made by Bribe, special thanks to Vexorian & Nestharus, version 4.1.0.1.
3 4 One map, one hashtable. Welcome to NewTable 4.1.0.15 6 This newest iteration of Table introduces the new HashTable struct.7 You can now instantiate HashTables which enables the use of large8 parent and large child keys, just like a standard hashtable. Previously,9 the user would have to instantiate a Table to do this on their own which -10 while doable - is something the user should not have to do if I can add it11 to this resource myself (especially if they are inexperienced).12 13 This library was originally called NewTable so it didn't conflict with14 the API of Table by Vexorian. However, the damage is done and it's too15 late to change the library name now. To help with damage control, I16 have provided an extension library called TableBC, which bridges all17 the functionality of Vexorian's Table except for 2-D string arrays &18 the ".flush(integer)" method. I use ".flush()" to flush a child hash-19 table, because I wanted the API in NewTable to reflect the API of real20 hashtables (I thought this would be more intuitive).21 22 API23 24 ------------25 struct Table26 | static method create takes nothing returns Table27 | create a new Table28 | 29 | method destroy takes nothing returns nothing30 | destroy it31 | 32 | method flush takes nothing returns nothing33 | flush all stored values inside of it34 | 35 | method remove takes integer key returns nothing36 | remove the value at index "key"37 | 38 | method operator []= takes integer key, $TYPE$ value returns nothing39 | assign "value" to index "key"40 | 41 | method operator [] takes integer key returns $TYPE$42 | load the value at index "key"43 | 44 | method has takes integer key returns boolean45 | whether or not the key was assigned46 |47 ----------------48 struct TableArray49 | static method operator [] takes integer array_size returns TableArray50 | create a new array of Tables of size "array_size"51 |52 | method destroy takes nothing returns nothing53 | destroy it54 |55 | method flush takes nothing returns nothing56 | flush and destroy it57 |58 | method operator size takes nothing returns integer59 | returns the size of the TableArray60 |61 | method operator [] takes integer key returns Table62 | returns a Table accessible exclusively to index "key"63 */64
65 globals66 private integer less = 0 //Index generation for TableArrays (below 0).
67 private integer more = 8190 //Index generation for Tables.
68 //Configure it if you use more than 8190 "key" variables in your map (this will never happen though).69
70 private hashtable ht = InitHashtable()
71 private key sizeK
72 private key listK
73 endglobals74
75 private struct dex extends array
76 static method operator size takes nothing returns Table
77 return sizeK78 endmethod79 static method operator list takes nothing returns Table
80 return listK81 endmethod82 endstruct83
84 private struct handles extends array
85 method has takes integer key returns boolean
86 return HaveSavedHandle(ht, this, key)
87 endmethod88 method remove takes integer key returns nothing
89 call RemoveSavedHandle(ht, this, key)
90 endmethod91 endstruct92
93 private struct agents extends array
94 method operator []= takes integer key, agent value returns nothing
95 call SaveAgentHandle(ht, this, key, value)
96 endmethod97 endstruct98
99 //! textmacro NEW_ARRAY_BASIC takes SUPER, FUNC, TYPE100 private struct $TYPE$s extends array
101 method operator [] takes integer key returns $TYPE$
102 return Load$FUNC$(ht, this, key)
103 endmethod104 method operator []= takes integer key, $TYPE$ value returns nothing
105 call Save$FUNC$(ht, this, key, value)
106 endmethod107 method has takes integer key returns boolean
108 return HaveSaved$SUPER$(ht, this, key)
109 endmethod110 method remove takes integer key returns nothing
111 call RemoveSaved$SUPER$(ht, this, key)
112 endmethod113 endstruct114 private module $TYPE$m
115 method operator $TYPE$ takes nothing returns $TYPE$s
116 return this
117 endmethod118 endmodule119 //! endtextmacro120
121 //! textmacro NEW_ARRAY takes FUNC, TYPE122 private struct $TYPE$s extends array
123 method operator [] takes integer key returns $TYPE$
124 return Load$FUNC$Handle(ht, this, key)
125 endmethod126 method operator []= takes integer key, $TYPE$ value returns nothing
127 call Save$FUNC$Handle(ht, this, key, value)
128 endmethod129 method has takes integer key returns boolean
130 return HaveSavedHandle(ht, this, key)
131 endmethod132 method remove takes integer key returns nothing
133 call RemoveSavedHandle(ht, this, key)
134 endmethod135 endstruct136 private module $TYPE$m
137 method operator $TYPE$ takes nothing returns $TYPE$s
138 return this
139 endmethod140 endmodule141 //! endtextmacro142
143 //Run these textmacros to include the entire hashtable API as wrappers.144 //Don't be intimidated by the number of macros - Vexorian's map optimizer is145 //supposed to kill functions which inline (all of these functions inline).146 //! runtextmacro NEW_ARRAY_BASIC("Real", "Real", "real")147 //! runtextmacro NEW_ARRAY_BASIC("Boolean", "Boolean", "boolean")148 //! runtextmacro NEW_ARRAY_BASIC("String", "Str", "string")149 //New textmacro to allow table.integer[] syntax for compatibility with textmacros that might desire it.150 //! runtextmacro NEW_ARRAY_BASIC("Integer", "Integer", "integer")151
152 //! runtextmacro NEW_ARRAY("Player", "player")153 //! runtextmacro NEW_ARRAY("Widget", "widget")154 //! runtextmacro NEW_ARRAY("Destructable", "destructable")155 //! runtextmacro NEW_ARRAY("Item", "item")156 //! runtextmacro NEW_ARRAY("Unit", "unit")157 //! runtextmacro NEW_ARRAY("Ability", "ability")158 //! runtextmacro NEW_ARRAY("Timer", "timer")159 //! runtextmacro NEW_ARRAY("Trigger", "trigger")160 //! runtextmacro NEW_ARRAY("TriggerCondition", "triggercondition")161 //! runtextmacro NEW_ARRAY("TriggerAction", "triggeraction")162 //! runtextmacro NEW_ARRAY("TriggerEvent", "event")163 //! runtextmacro NEW_ARRAY("Force", "force")164 //! runtextmacro NEW_ARRAY("Group", "group")165 //! runtextmacro NEW_ARRAY("Location", "location")166 //! runtextmacro NEW_ARRAY("Rect", "rect")167 //! runtextmacro NEW_ARRAY("BooleanExpr", "boolexpr")168 //! runtextmacro NEW_ARRAY("Sound", "sound")169 //! runtextmacro NEW_ARRAY("Effect", "effect")170 //! runtextmacro NEW_ARRAY("UnitPool", "unitpool")171 //! runtextmacro NEW_ARRAY("ItemPool", "itempool")172 //! runtextmacro NEW_ARRAY("Quest", "quest")173 //! runtextmacro NEW_ARRAY("QuestItem", "questitem")174 //! runtextmacro NEW_ARRAY("DefeatCondition", "defeatcondition")175 //! runtextmacro NEW_ARRAY("TimerDialog", "timerdialog")176 //! runtextmacro NEW_ARRAY("Leaderboard", "leaderboard")177 //! runtextmacro NEW_ARRAY("Multiboard", "multiboard")178 //! runtextmacro NEW_ARRAY("MultiboardItem", "multiboarditem")179 //! runtextmacro NEW_ARRAY("Trackable", "trackable")180 //! runtextmacro NEW_ARRAY("Dialog", "dialog")181 //! runtextmacro NEW_ARRAY("Button", "button")182 //! runtextmacro NEW_ARRAY("TextTag", "texttag")183 //! runtextmacro NEW_ARRAY("Lightning", "lightning")184 //! runtextmacro NEW_ARRAY("Image", "image")185 //! runtextmacro NEW_ARRAY("Ubersplat", "ubersplat")186 //! runtextmacro NEW_ARRAY("Region", "region")187 //! runtextmacro NEW_ARRAY("FogState", "fogstate")188 //! runtextmacro NEW_ARRAY("FogModifier", "fogmodifier")189 //! runtextmacro NEW_ARRAY("Hashtable", "hashtable")190
191 struct Table extends array
192
193 // Implement modules for intuitive syntax (tb.handle; tb.unit; etc.)194 implement realm195 implement integerm196 implement booleanm197 implement stringm198 implement playerm199 implement widgetm200 implement destructablem201 implement itemm202 implement unitm203 implement abilitym204 implement timerm205 implement triggerm206 implement triggerconditionm207 implement triggeractionm208 implement eventm209 implement forcem210 implement groupm211 implement locationm212 implement rectm213 implement boolexprm214 implement soundm215 implement effectm216 implement unitpoolm217 implement itempoolm218 implement questm219 implement questitemm220 implement defeatconditionm221 implement timerdialogm222 implement leaderboardm223 implement multiboardm224 implement multiboarditemm225 implement trackablem226 implement dialogm227 implement buttonm228 implement texttagm229 implement lightningm230 implement imagem231 implement ubersplatm232 implement regionm233 implement fogstatem234 implement fogmodifierm235 implement hashtablem236
237 method operator handle takes nothing returns handles
238 return this
239 endmethod240
241 method operator agent takes nothing returns agents
242 return this
243 endmethod244
245 //set this = tb[GetSpellAbilityId()]246 method operator [] takes integer key returns Table
247 return LoadInteger(ht, this, key) //return this.integer[key]
248 endmethod249
250 //set tb[389034] = 8192251 method operator []= takes integer key, Table tb returns nothing
252 call SaveInteger(ht, this, key, tb) //set this.integer[key] = tb
253 endmethod254
255 //set b = tb.has(2493223)256 method has takes integer key returns boolean
257 return HaveSavedInteger(ht, this, key) //return this.integer.has(key)
258 endmethod259
260 //call tb.remove(294080)261 method remove takes integer key returns nothing
262 call RemoveSavedInteger(ht, this, key) //call this.integer.remove(key)
263 endmethod264
265 //Remove all data from a Table instance266 method flush takes nothing returns nothing
267 call FlushChildHashtable(ht, this)
268 endmethod269
270 //local Table tb = Table.create()271 static method create takes nothing returns Table
272 local Table this = dex.list[0]
273
274 if this == 0 then
275 set this = more + 1
276 set more = this
277 else278 set dex.list[0] = dex.list[this]
279 call dex.list.remove(this) //Clear hashed memory
280 endif281
282 debug set dex.list[this] = -1
283 return this
284 endmethod285
286 // Removes all data from a Table instance and recycles its index.287 //288 // call tb.destroy()289 //290 method destroy takes nothing returns nothing
291 debug if dex.list[this] != -1 then
292 debug call BJDebugMsg("Table Error: Tried to double-free instance: " + I2S(this))
293 debug return
294 debug endif
295
296 call this.flush()
297
298 set dex.list[this] = dex.list[0]
299 set dex.list[0] = this
300 endmethod301
302 //! runtextmacro optional TABLE_BC_METHODS()303 endstruct304
305 //! runtextmacro optional TABLE_BC_STRUCTS()306
307 struct TableArray extends array
308
309 //Returns a new TableArray to do your bidding. Simply use:310 //311 // local TableArray ta = TableArray[array_size]312 //313 static method operator [] takes integer array_size returns TableArray
314 local Table tb = dex.size[array_size] //Get the unique recycle list for this array size
315 local TableArray this = tb[0] //The last-destroyed TableArray that had this array size
316
317 debug if array_size <= 0 then
318 debug call BJDebugMsg("TypeError: Invalid specified TableArray size: " + I2S(array_size))
319 debug return 0
320 debug endif
321
322 if this == 0 then
323 set this = less - array_size
324 set less = this
325 else326 set tb[0] = tb[this] //Set the last destroyed to the last-last destroyed
327 call tb.remove(this) //Clear hashed memory
328 endif329
330 set dex.size[this] = array_size //This remembers the array size
331 return this
332 endmethod333
334 //Returns the size of the TableArray335 method operator size takes nothing returns integer
336 return dex.size[this]
337 endmethod338
339 //This magic method enables two-dimensional[array][syntax] for Tables,340 //similar to the two-dimensional utility provided by hashtables them-341 //selves.342 //343 //ta[integer a].unit[integer b] = unit u344 //ta[integer a][integer c] = integer d345 //346 //Inline-friendly when not running in debug mode347 //348 method operator [] takes integer key returns Table
349 static if DEBUG_MODE then
350 local integer i = this.size
351 if i == 0 then
352 call BJDebugMsg("IndexError: Tried to get key from invalid TableArray instance: " + I2S(this))
353 return 0
354 elseif key < 0 or key >= i then
355 call BJDebugMsg("IndexError: Tried to get key [" + I2S(key) + "] from outside TableArray bounds: " + I2S(i))
356 return 0
357 endif358 endif359 return this + key
360 endmethod361
362 //Destroys a TableArray without flushing it; I assume you call .flush()363 //if you want it flushed too. This is a public method so that you don't364 //have to loop through all TableArray indices to flush them if you don't365 //need to (ie. if you were flushing all child-keys as you used them).366 //367 method destroy takes nothing returns nothing
368 local Table tb = dex.size[this.size]
369
370 debug if this.size == 0 then
371 debug call BJDebugMsg("TypeError: Tried to destroy an invalid TableArray: " + I2S(this))
372 debug return
373 debug endif
374
375 if tb == 0 then
376 //Create a Table to index recycled instances with their array size377 set tb = Table.create()
378 set dex.size[this.size] = tb
379 endif380
381 call dex.size.remove(this) //Clear the array size from hash memory
382
383 set tb[this] = tb[0]
384 set tb[0] = this
385 endmethod386
387 private static Table tempTable
388 private static integer tempEnd
389
390 //Avoids hitting the op limit391 private static method clean takes nothing returns nothing
392 local Table tb = .tempTable
393 local integer end = tb + 0x1000
394 if end < .tempEnd then
395 set .tempTable = end
396 call ForForce(bj_FORCE_PLAYER[0], function thistype.clean)
397 else398 set end = .tempEnd
399 endif400 loop401 call tb.flush()
402 set tb = tb + 1
403 exitwhen tb == end
404 endloop405 endmethod406
407 //Flushes the TableArray and also destroys it. Doesn't get any more408 //similar to the FlushParentHashtable native than this.409 //410 method flush takes nothing returns nothing
411 debug if this.size == 0 then
412 debug call BJDebugMsg("TypeError: Tried to flush an invalid TableArray instance: " + I2S(this))
413 debug return
414 debug endif
415 set .tempTable = this
416 set .tempEnd = this + this.size
417 call ForForce(bj_FORCE_PLAYER[0], function thistype.clean)
418 call this.destroy()
419 endmethod420
421 endstruct422
423 //NEW: Added in Table 4.0. A fairly simple struct but allows you to do more424 //than that which was previously possible.425 struct HashTable extends array
426 427 //Enables myHash[parentKey][childKey] syntax.428 //Basically, it creates a Table in the place of the parent key if429 //it didn't already get created earlier.430 method operator [] takes integer index returns Table
431 local Table t = Table(this)[index]
432 if t == 0 then
433 set t = Table.create()
434 set Table(this)[index] = t //whoops! Forgot that line. I'm out of practice!
435 endif436 return t437 endmethod438 439 //You need to call this on each parent key that you used if you440 //intend to destroy the HashTable or simply no longer need that key.441 method remove takes integer index returns nothing
442 local Table t = Table(this)[index]
443 if t != 0 then
444 call t.destroy()
445 call Table(this).remove(index)
446 endif447 endmethod448
449 //Added in version 4.1450 method has takes integer index returns boolean
451 return Table(this).has(index)
452 endmethod453
454 //HashTables are just fancy Table indices.455 method destroy takes nothing returns nothing
456 call Table(this).destroy()
457 endmethod458
459 //Like I said above...460 static method create takes nothing returns thistype
461 return Table.create()
462 endmethod463 464 endstruct465 466 endlibrary467
Example usage of HashTable
1 2 local HashTable hash = HashTable.create() //create it
3 set hash['hfoo'][StringHash("poop")] = 66 //access large parent and child keys as needed
4 set hash['hfoo'].unit[99999] = GetTriggerUnit() //still works with multiple-type syntax so you still have the full hashtable API.
5 call hash.remove('hfoo') //This literally is calling FlushChildHashtable, and should be used when the parentkey and/or HashTable are to be retired
6 call hash.destroy() //DOES NOT FLUSH THE HASHTABLE. You must manually remove each parent key, first, otherwise you'll have a lot of leaked Tables.
7
Backwards Compatibility with Vexorian's Table
1 2 library TableBC requires Table
3 /*4 Backwards-compatibility add-on for scripts employing Vexorian's Table.5
6 Added 31 July 2015: introduced static method operator [] and7 static method flush2D for Table, HandleTable and StringTable. Now,8 almost all of the Vexorian API has been replicated (minus the .flush paradox).9
10 The Table library itself was unchanged to implement these11 enhancements, so you need only update this library to experience the12 improved syntax compatibility.13 14 Disclaimer:15 16 The following error does not occur with HandleTables & StringTables, only17 with the standard, integer-based Table, so you do not need to make any18 changes to StringTable/HandleTable-employing scripts.19 20 The this.flush(key) method from the original Table cannot be parsed with21 the new Table. For the scripts that use this method, they need to be up-22 dated to use the more fitting this.remove(key) method.23 24 Please don't try using StringTables/HandleTables with features exclusive25 to the new Table as they will cause syntax errors. I do not have any plan26 to endorse these types of Tables because delegation in JassHelper is not27 advanced enough for three types of Tables without copying every single28 method over again (as you can see this already generates plenty of code).29 StringTable & HandleTable are wrappers for StringHash & GetHandleId, so30 just type them out.31 */32 33 //! textmacro TABLE_BC_METHODS34 method reset takes nothing returns nothing
35 call this.flush()
36 endmethod37 method exists takes integer key returns boolean
38 return this.has(key)
39 endmethod40 static method operator [] takes string id returns Table
41 local integer index = StringHash(id)
42 local Table t = Table(thistype.typeid)[index]
43 if t == 0 then
44 set t = Table.create()
45 set Table(thistype.typeid)[index] = t
46 endif47 return t48 endmethod49 static method flush2D takes string id returns nothing
50 local integer index = StringHash(id)
51 local Table t = Table(thistype.typeid)[index]
52 if t != 0 then
53 call t.destroy()
54 call Table(thistype.typeid).remove(index)
55 endif56 endmethod57 //! endtextmacro58 59 //! textmacro TABLE_BC_STRUCTS60 struct HandleTable extends array
61 static method operator [] takes string index returns thistype
62 return Table[index]
63 endmethod64 static method flush2D takes string index returns nothing
65 call Table.flush2D(index)
66 endmethod67 method operator [] takes handle key returns integer
68 return Table(this)[GetHandleId(key)]
69 endmethod70 method operator []= takes handle key, integer value returns nothing
71 set Table(this)[GetHandleId(key)] = value
72 endmethod73 method flush takes handle key returns nothing
74 call Table(this).remove(GetHandleId(key))
75 endmethod76 method exists takes handle key returns boolean
77 return Table(this).has(GetHandleId(key))
78 endmethod79 method reset takes nothing returns nothing
80 call Table(this).flush()
81 endmethod82 method destroy takes nothing returns nothing
83 call Table(this).destroy()
84 endmethod85 static method create takes nothing returns thistype
86 return Table.create()
87 endmethod88 endstruct89 90 struct StringTable extends array
91 static method operator [] takes string index returns thistype
92 return Table[index]
93 endmethod94 static method flush2D takes string index returns nothing
95 call Table.flush2D(index)
96 endmethod97 method operator [] takes string key returns integer
98 return Table(this)[StringHash(key)]
99 endmethod100 method operator []= takes string key, integer value returns nothing
101 set Table(this)[StringHash(key)] = value
102 endmethod103 method flush takes string key returns nothing
104 call Table(this).remove(StringHash(key))
105 endmethod106 method exists takes string key returns boolean
107 return Table(this).has(StringHash(key))
108 endmethod109 method reset takes nothing returns nothing
110 call Table(this).flush()
111 endmethod112 method destroy takes nothing returns nothing
113 call Table(this).destroy()
114 endmethod115 static method create takes nothing returns thistype
116 return Table.create()
117 endmethod118 endstruct119 //! endtextmacro120 121 endlibrary122
Example Usage of Table:
1 2 struct table_demo extends array
3 private static method demo takes nothing returns nothing
4 //Create it:5 local Table a = Table.create()
6
7 //Use it:8 local boolean b = a.has(69)
9 set a[654321] = 'A'
10 set a[54321] = 'B'
11 set a.unit[12345] = GetTriggerUnit()
12 set a.unit[GetHandleId(a.unit[12345])] = GetSpellTargetUnit()
13 set a.real['ABCD'] = 3.14159
14 set a.integer[133] = 21
15 16 //remove entries17 call a.handle.remove('ABCD')
18 call a.remove(54321)
19 20 //Flush/destroy it:21 call a.destroy()
22 23 //Or, only flush it:24 call a.flush()
25 endmethod26 endstruct27
Example Usage of TableArray:
1 2 //Create it:3 local TableArray da = TableArray[0x2000]
4
5 //Use it:6 local thistype this = 0
7 loop8 set this = this.next
9 exitwhen this == 0
10 set this.save = this.save + 1
11 set da[this].real[this.save * 3] = GetUnitX(this.unit)
12 set da[this].real[this.save * 3 + 1] = GetUnitY(this.unit)
13 set da[this].real[this.save * 3 + 2] = GetUnitFlyHeight(this.unit)
14 endloop15
16 //Flush/destroy it:17 call da.flush()
18
19 //Or, only destroy it (more efficient if you manage memory yourself)20 call da.destroy()
21
Note the power of TableArray, how it splices the one hashtable into a many-dimensional array. This means you can have a multi-dimensional array (and more) per system.