[Snippet] New Table

Scripts

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.

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.

Code (jass) Select
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.1
5
   
6
    This newest iteration of Table introduces the new HashTable struct.
7
    You can now instantiate HashTables which enables the use of large
8
    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 it
11
    to this resource myself (especially if they are inexperienced).
12
   
13
    This library was originally called NewTable so it didn't conflict with
14
    the API of Table by Vexorian. However, the damage is done and it's too
15
    late to change the library name now. To help with damage control, I
16
    have provided an extension library called TableBC, which bridges all
17
    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 real
20
    hashtables (I thought this would be more intuitive).
21
   
22
    API
23
   
24
    ------------
25
    struct Table
26
    | static method create takes nothing returns Table
27
    |     create a new Table
28
    |   
29
    | method destroy takes nothing returns nothing
30
    |     destroy it
31
    |   
32
    | method flush takes nothing returns nothing
33
    |     flush all stored values inside of it
34
    |   
35
    | method remove takes integer key returns nothing
36
    |     remove the value at index "key"
37
    |   
38
    | method operator []= takes integer key, $TYPE$ value returns nothing
39
    |     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 boolean
45
    |     whether or not the key was assigned
46
    |
47
    ----------------
48
    struct TableArray
49
    | static method operator [] takes integer array_size returns TableArray
50
    |     create a new array of Tables of size "array_size"
51
    |
52
    | method destroy takes nothing returns nothing
53
    |     destroy it
54
    |
55
    | method flush takes nothing returns nothing
56
    |     flush and destroy it
57
    |
58
    | method operator size takes nothing returns integer
59
    |     returns the size of the TableArray
60
    |
61
    | method operator [] takes integer key returns Table
62
    |     returns a Table accessible exclusively to index "key"
63
*/
64
   
65
globals
66
    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
endglobals
74
   
75
private struct dex extends array
76
    static method operator size takes nothing returns Table
77
        return sizeK
78
    endmethod
79
    static method operator list takes nothing returns Table
80
        return listK
81
    endmethod
82
endstruct
83
   
84
private struct handles extends array
85
    method has takes integer key returns boolean
86
        return HaveSavedHandle(ht, this, key)
87
    endmethod
88
    method remove takes integer key returns nothing
89
        call RemoveSavedHandle(ht, this, key)
90
    endmethod
91
endstruct
92
   
93
private struct agents extends array
94
    method operator []= takes integer key, agent value returns nothing
95
        call SaveAgentHandle(ht, this, key, value)
96
    endmethod
97
endstruct
98
   
99
//! textmacro NEW_ARRAY_BASIC takes SUPER, FUNC, TYPE
100
private struct $TYPE$s extends array
101
    method operator [] takes integer key returns $TYPE$
102
        return Load$FUNC$(ht, this, key)
103
    endmethod
104
    method operator []= takes integer key, $TYPE$ value returns nothing
105
        call Save$FUNC$(ht, this, key, value)
106
    endmethod
107
    method has takes integer key returns boolean
108
        return HaveSaved$SUPER$(ht, this, key)
109
    endmethod
110
    method remove takes integer key returns nothing
111
        call RemoveSaved$SUPER$(ht, this, key)
112
    endmethod
113
endstruct
114
private module $TYPE$m
115
    method operator $TYPE$ takes nothing returns $TYPE$s
116
        return this
117
    endmethod
118
endmodule
119
//! endtextmacro
120
   
121
//! textmacro NEW_ARRAY takes FUNC, TYPE
122
private struct $TYPE$s extends array
123
    method operator [] takes integer key returns $TYPE$
124
        return Load$FUNC$Handle(ht, this, key)
125
    endmethod
126
    method operator []= takes integer key, $TYPE$ value returns nothing
127
        call Save$FUNC$Handle(ht, this, key, value)
128
    endmethod
129
    method has takes integer key returns boolean
130
        return HaveSavedHandle(ht, this, key)
131
    endmethod
132
    method remove takes integer key returns nothing
133
        call RemoveSavedHandle(ht, this, key)
134
    endmethod
135
endstruct
136
private module $TYPE$m
137
    method operator $TYPE$ takes nothing returns $TYPE$s
138
        return this
139
    endmethod
140
endmodule
141
//! endtextmacro
142
   
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 is
145
//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 realm
195
    implement integerm
196
    implement booleanm
197
    implement stringm
198
    implement playerm
199
    implement widgetm
200
    implement destructablem
201
    implement itemm
202
    implement unitm
203
    implement abilitym
204
    implement timerm
205
    implement triggerm
206
    implement triggerconditionm
207
    implement triggeractionm
208
    implement eventm
209
    implement forcem
210
    implement groupm
211
    implement locationm
212
    implement rectm
213
    implement boolexprm
214
    implement soundm
215
    implement effectm
216
    implement unitpoolm
217
    implement itempoolm
218
    implement questm
219
    implement questitemm
220
    implement defeatconditionm
221
    implement timerdialogm
222
    implement leaderboardm
223
    implement multiboardm
224
    implement multiboarditemm
225
    implement trackablem
226
    implement dialogm
227
    implement buttonm
228
    implement texttagm
229
    implement lightningm
230
    implement imagem
231
    implement ubersplatm
232
    implement regionm
233
    implement fogstatem
234
    implement fogmodifierm
235
    implement hashtablem
236
   
237
    method operator handle takes nothing returns handles
238
        return this
239
    endmethod
240
   
241
    method operator agent takes nothing returns agents
242
        return this
243
    endmethod
244
   
245
    //set this = tb[GetSpellAbilityId()]
246
    method operator [] takes integer key returns Table
247
        return LoadInteger(ht, this, key) //return this.integer[key]
248
    endmethod
249
   
250
    //set tb[389034] = 8192
251
    method operator []= takes integer key, Table tb returns nothing
252
        call SaveInteger(ht, this, key, tb) //set this.integer[key] = tb
253
    endmethod
254
   
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
    endmethod
259
   
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
    endmethod
264
   
265
    //Remove all data from a Table instance
266
    method flush takes nothing returns nothing
267
        call FlushChildHashtable(ht, this)
268
    endmethod
269
   
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
        else
278
            set dex.list[0] = dex.list[this]
279
            call dex.list.remove(this) //Clear hashed memory
280
        endif
281
       
282
        debug set dex.list[this] = -1
283
        return this
284
    endmethod
285
   
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
    endmethod
301
   
302
    //! runtextmacro optional TABLE_BC_METHODS()
303
endstruct
304
   
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
        else
326
            set tb[0] = tb[this]  //Set the last destroyed to the last-last destroyed
327
            call tb.remove(this)  //Clear hashed memory
328
        endif
329
       
330
        set dex.size[this] = array_size //This remembers the array size
331
        return this
332
    endmethod
333
   
334
    //Returns the size of the TableArray
335
    method operator size takes nothing returns integer
336
        return dex.size[this]
337
    endmethod
338
   
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 u
344
    //ta[integer a][integer c] = integer d
345
    //
346
    //Inline-friendly when not running in debug mode
347
    //
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
            endif
358
        endif
359
        return this + key
360
    endmethod
361
   
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't
364
    //have to loop through all TableArray indices to flush them if you don't
365
    //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 size
377
            set tb = Table.create()
378
            set dex.size[this.size] = tb
379
        endif
380
       
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
    endmethod
386
   
387
    private static Table tempTable
388
    private static integer tempEnd
389
   
390
    //Avoids hitting the op limit
391
    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
        else
398
            set end = .tempEnd
399
        endif
400
        loop
401
            call tb.flush()
402
            set tb = tb + 1
403
            exitwhen tb == end
404
        endloop
405
    endmethod
406
   
407
    //Flushes the TableArray and also destroys it. Doesn't get any more
408
    //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
    endmethod
420
   
421
endstruct
422
   
423
//NEW: Added in Table 4.0. A fairly simple struct but allows you to do more
424
//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 if
429
    //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
        endif
436
        return t
437
    endmethod
438
439
    //You need to call this on each parent key that you used if you
440
    //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
        endif
447
    endmethod
448
   
449
    //Added in version 4.1
450
    method has takes integer index returns boolean
451
        return Table(this).has(index)
452
    endmethod
453
   
454
    //HashTables are just fancy Table indices.
455
    method destroy takes nothing returns nothing
456
        call Table(this).destroy()
457
    endmethod
458
   
459
    //Like I said above...
460
    static method create takes nothing returns thistype
461
        return Table.create()
462
    endmethod
463
464
endstruct
465
466
endlibrary
467


Example usage of HashTable
Code (jass) Select
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
Code (jass) Select
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 [] and
7
    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 these
11
    enhancements, so you need only update this library to experience the
12
    improved syntax compatibility.
13
   
14
    Disclaimer:
15
   
16
    The following error does not occur with HandleTables & StringTables, only
17
    with the standard, integer-based Table, so you do not need to make any
18
    changes to StringTable/HandleTable-employing scripts.
19
   
20
    The this.flush(key) method from the original Table cannot be parsed with
21
    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 exclusive
25
    to the new Table as they will cause syntax errors. I do not have any plan
26
    to endorse these types of Tables because delegation in JassHelper is not
27
    advanced enough for three types of Tables without copying every single
28
    method over again (as you can see this already generates plenty of code).
29
    StringTable & HandleTable are wrappers for StringHash & GetHandleId, so
30
    just type them out.
31
*/
32
33
//! textmacro TABLE_BC_METHODS
34
    method reset takes nothing returns nothing
35
        call this.flush()
36
    endmethod
37
    method exists takes integer key returns boolean
38
        return this.has(key)
39
    endmethod
40
    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
        endif
47
        return t
48
    endmethod
49
    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
        endif
56
    endmethod
57
//! endtextmacro
58
59
//! textmacro TABLE_BC_STRUCTS
60
struct HandleTable extends array
61
    static method operator [] takes string index returns thistype
62
        return Table[index]
63
    endmethod
64
    static method flush2D takes string index returns nothing
65
        call Table.flush2D(index)
66
    endmethod
67
    method operator [] takes handle key returns integer
68
        return Table(this)[GetHandleId(key)]
69
    endmethod
70
    method operator []= takes handle key, integer value returns nothing
71
        set Table(this)[GetHandleId(key)] = value
72
    endmethod
73
    method flush takes handle key returns nothing
74
        call Table(this).remove(GetHandleId(key))
75
    endmethod
76
    method exists takes handle key returns boolean
77
        return Table(this).has(GetHandleId(key))
78
    endmethod
79
    method reset takes nothing returns nothing
80
        call Table(this).flush()
81
    endmethod
82
    method destroy takes nothing returns nothing
83
        call Table(this).destroy()
84
    endmethod
85
    static method create takes nothing returns thistype
86
        return Table.create()
87
    endmethod
88
endstruct
89
90
struct StringTable extends array
91
    static method operator [] takes string index returns thistype
92
        return Table[index]
93
    endmethod
94
    static method flush2D takes string index returns nothing
95
        call Table.flush2D(index)
96
    endmethod
97
    method operator [] takes string key returns integer
98
        return Table(this)[StringHash(key)]
99
    endmethod
100
    method operator []= takes string key, integer value returns nothing
101
        set Table(this)[StringHash(key)] = value
102
    endmethod
103
    method flush takes string key returns nothing
104
        call Table(this).remove(StringHash(key))
105
    endmethod
106
    method exists takes string key returns boolean
107
        return Table(this).has(StringHash(key))
108
    endmethod
109
    method reset takes nothing returns nothing
110
        call Table(this).flush()
111
    endmethod
112
    method destroy takes nothing returns nothing
113
        call Table(this).destroy()
114
    endmethod
115
    static method create takes nothing returns thistype
116
        return Table.create()
117
    endmethod
118
endstruct
119
//! endtextmacro
120
121
endlibrary
122

Example Usage of Table:
Code (jass) Select
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 entries
17
        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
    endmethod
26
endstruct
27

Example Usage of TableArray:
Code (jass) Select
1
2
//Create it:
3
local TableArray da = TableArray[0x2000]
4
 
5
//Use it:
6
local thistype this = 0
7
loop
8
    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
endloop
15
 
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.