• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!

[Containers] Array<T>

Level 26
Joined
Mar 19, 2008
Messages
3,140
Implementation of static contiguous array. Merely adds any functionality.
Basically, its designed to increase the functionality of <type> array and also allows to create an array of objects. Data is stored within underlying Table object.
Complexity is constant across all functions except for copy ctor where it's linear to the value of size. Unlike in standard std::array<T> where swap member performs swap operations across all elements, I've used quick, more practical method that seems to fit better in jass especially when using Table.

Requires copy ctor in form of static method operator [] to provide correct results when working with objects. This element is subject that can be changed.

Requires newest Table update.
Huge applause goes to Bribe for updating his amazing Table to better accommodate this resource.
JASS:
/*****************************************************************************
*
*    Array<T> v1.0.2.1
*       by Bannar aka Spinnaker
*
*    Static contiguous array.
*    Designed to provide <type> array functionality merely adding a layer of member functions
*
******************************************************************************
*    
*    Requirements:
*       Table by Bribe
*          hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
*
******************************************************************************
*
*    Implementation:
*
*       macro DEFINE_ARRAY takes NAME, TYPE, SIZE, DEFAULT, OBJECT
*
*          NAME - sets name of array type
*          TYPE - type of values stored
*          SIZE - static size of array type
*          DEFAULT - default value for type TYPE
*          OBJECT - boolean, tells whether array stores struct objects or not
*
******************************************************************************
*
*    struct API:
*
*       static constant string valueType
*
*       static method create takes nothing returns thistype
*          default ctor
*
*       static method operator[] takes thistype arr returns thistype
*          copy ctor
*
*       method destroy takes nothing returns nothing
*          default dctor
*
*       method front takes nothing returns $TYPE$
*          retrieves first element
*
*       method back takes nothing returns $TYPE$
*          retrieves last element
*
*       method at takes integer index returns $TYPE$
*          returns item at position index; performs bound check
*
*       method operator[] takes integer index returns $TYPE$
*          returns item at position index; does not check boundary
*
*       method operator[]= takes integer index, $TYPE$ value returns nothing
*          sets item at index to value
*
*       method data takes nothing returns Table
*          returns the underlying Table object
*
*       method empty takes nothing returns boolean
*          checks if array if empty
*
*       method size takes nothing returns integer
*          returns size of an array; constant
*
*       method clear takes nothing returns nothing
*          performs a flush operation on data Table
*
*       method fill takes $TYPE$ value returns nothing
*          fills array with values 'value' of type TYPE
*
******************************************************************************/
library ArrayTemplate requires Table

//! textmacro_once DEFINE_ARRAY takes NAME, TYPE, SIZE, DEFAULT, OBJECT
struct $NAME$ extends array
    static constant string valueType = "$TYPE$"

    private method operator table takes nothing returns Table
        return this
    endmethod

    private method seT takes integer index, $TYPE$ value returns nothing
        static if $OBJECT$ then
            set table[index] = $TYPE$[value]
        else
            set table.$TYPE$[index] = value
        endif
    endmethod

    private method get takes integer index returns $TYPE$
        static if $OBJECT$ then
            return table[index]
        else
            return table.$TYPE$[index]
        endif
    endmethod

    static method create takes nothing returns thistype
        return Table.create()
    endmethod

    method clear takes nothing returns nothing

    static if $OBJECT$ then
        local integer obj = 0
        loop
            exitwhen obj >= $SIZE$
            call table[obj].destroy()
            set obj = obj + 1
        endloop
    endif

        call table.flush()
    endmethod

    method destroy takes nothing returns nothing
        call clear()
        call table.destroy()
    endmethod

    method front takes nothing returns $TYPE$
        return get(0)
    endmethod

    method back takes nothing returns $TYPE$
        return get($SIZE$-1)
    endmethod

    method at takes integer index returns $TYPE$
        if not ( index >= 0 and index < $SIZE$ )then
            // DEBUG invalid index
            return $DEFAULT$
        else
            return get(index)
        endif
    endmethod

    method operator[] takes integer index returns $TYPE$
        return get(index)
    endmethod

    method operator[]= takes integer index, $TYPE$ value returns nothing
        if index >= $SIZE$ then
            // DEBUG invalid index
            return
        endif
        call seT(index, value)
    endmethod

    static method operator[] takes thistype arr returns thistype
        local thistype this = thistype.create()
        local integer i = 0
        loop
            exitwhen i >= $SIZE$
            call this.seT(i, arr[i])
            set i = i + 1
        endloop
        return this
    endmethod

    method data takes nothing returns Table
        return this
    endmethod

    method empty takes nothing returns boolean
        return $SIZE$ == 0
    endmethod

    method size takes nothing returns integer
        return $SIZE$
    endmethod

    method fill takes $TYPE$ value returns nothing
        local integer i = 0
        loop
            exitwhen i >= $SIZE$
            call seT(i, value)
            set i = i + 1
        endloop
    endmethod

endstruct
//! endtextmacro

endlibrary
Demo:
JASS:
//! runtextmacro DEFINE_ARRAY("Array", "integer", "9", "0", "false")
//! runtextmacro DEFINE_ARRAY("StrArray", "string", "7", "\"\"", "false")
//! runtextmacro DEFINE_ARRAY("ArrayOfArr", "Array", "3", "0", "true")

struct test_array_struct extends array

    static method print takes Table tb, integer size, string prefix returns nothing
        local integer i = size
        local string s = ""
        loop
            exitwhen 0 == i
            set i = i-1
            set s = I2S(tb[i]) + ", " + s
        endloop
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, prefix + s)
        set s = null
    endmethod

    static method test_array takes nothing returns nothing
        local integer max = 9
        local integer i
        local integer j
        local string s
        local Array arr = Array.create()
        local Array arr2 = Array.create()
        local ArrayOfArr aoa = ArrayOfArr.create()

        set arr[0] = 55
        set arr[1] = 3
        set arr[2] = 88
        set arr[3] = 9
        set arr[4] = -10
        set arr[5] = 1
        set arr[6] = 17
        set arr[7] = -1
        set arr[8] = 26

        call aoa.fill(arr)
        set aoa[0][1] = 66

        set arr2[0] = 4
        set arr2[1] = 55
        set arr2[2] = 0
        set arr2[3] = 13
        set arr2[4] = 7

        /* performed without print method to show that array of objects achieves
           in this case double array syntax [][] similar to one from TableArray */
        set i=aoa.size()-1
        loop
            set s = ""
            set j = aoa[i].size()-1
            exitwhen i < 0
            loop
                exitwhen j < 0
                set s = I2S(aoa[i][j]) + ", " + s
                set j = j - 1
            endloop
            call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"Array: (" + I2S(i) +") holds: " + s)
            set i = i - 1
        endloop

        call print(arr.data(), arr.size(), "Arr: ")
        call print(arr2.data(), arr2.size(), "Arr2: ")
    endmethod

    private static method onInit takes nothing returns nothing
        call TimerStart(CreateTimer(), 2, false, function thistype.test_array)
    endmethod
endstruct
 
Last edited:
Level 26
Joined
Mar 19, 2008
Messages
3,140
Updated.

Code is a bit cleaner now, even though it was elegant already. Added support for .destroy() method if array is defined for struct type instead of handles or primitives. Whenever clear or destroy method is called for array instance, prior to proceeding with array itself, set of object nodes will be destroy and thus deallocated (do you deallocate your struct instance within destroy method, dont you?).
 
Level 26
Joined
Mar 19, 2008
Messages
3,140
The same way I divided structs in Real2D where allocation/deallocation was based on parent struct? Child struct included just additional api.

In such case:
JASS:
    static method create takes nothing returns thistype
        local thistype this = thistype(Table.create())
        set this.table = Table(this)
        return this
    endmethod
I'd like to keep "table" member; it seems intuitive, however, this can also be removed if you wish. Script would be spammed with: Table(this)
Ctor:
JASS:
    static method create takes nothing returns thistype
        return thistype(Table.create())
    endmethod
Your call.
 
Level 26
Joined
Mar 19, 2008
Messages
3,140
Swap operation is useful the same way std::swap (specialized for array:: in this case) is. There is nothing else to say.

If you really want to (meaning this cant get approved without ;p) I can get rid of static table array member. I could also include constant boolean: "USE_SWAP", although, this requires static ifs just for case where you do/do not want swap. Is keeping 1 array hurts that much?

Edit: Updated. Now extends Table as suggested. No longer requires Alloc, thus library itself has no allocator availble. This also decreases code block a bit.
 
Top