1. Find your way through the deepest dungeon in the 18th Mini Mapping Contest Poll.
    Dismiss Notice
  2. A brave new world lies beyond the seven seas. Join the 34th Modeling Contest today!
    Dismiss Notice
  3. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
Hive 3 Remoosed BETA - NOW LIVE. Go check it out at BETA Hive Workshop! Post your feedback in this new forum BETA Feedback.
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Shared Memory

Discussion in '"Graveyard"' started by WaterKnight, Dec 28, 2010.

  1. WaterKnight

    WaterKnight

    Joined:
    Aug 18, 2009
    Messages:
    4,035
    Resources:
    5
    Maps:
    1
    Tutorials:
    4
    Resources:
    5
    Note: Ignore the hidden codes in case you are not familiar with my other system Structfollowers. My main purpose to start this thread was to tell of concepts, not how the result realization should look like.

    Exposition
    You can only have a certain amount of hashtables[1]. One hashtable suffices for most things, that's why I'd like to divide it neatly, instead of using multiples. vJass provides the key-function, that delivers another integer each time, so you can use them as keys in a hashtable. Even so, said function only gives you a one-dimensional series of numbers, you won't get another series that includes all of them again. That's why, in my opinion, the function should be used for the main table, specific tables will have their own way to obtain keys anyway[2]. Additionally, the key function starts at 0 or 1 to give out keys, not at the integer minimum[3], that method already blasts away half of the 4 billion slots. This does not please me - I try to change it. Furthermore, you often need a third dimension in the table to dedicate an undetermined amount of abilities to a unit for example and this unit already requires one of the two keys[4]. So I chop up the available keys in portions, to carve out a third dimension, so each unit receives a whole array of keys for use. In order to still being effective, I fragment the data, I don't dynamically reset the tables' positions where they fit but have a static max size. Thus it's crucial that when I want to assign arrays of values to an object, I only pass the first key and all other ones get calculated by the position index in the array, hence are reserved for this one array.

    1. (you won't break this limit easily though unless you have a system that dynamically allocates them or you have an arithmetic array)
    2. (e.g. by multiplication or powers)
    3. -(2^8)^4/2 = -2^31 = -2147483648
    4. (or at least is included in one of the keys)

    The basic idea is

    Code (vJASS):
    //! textmacro GetKey takes name
        static key $name$_BASE

        static constant integer $name$ = Math.Integer.MIN + $name$_BASE
    //! endtextmacro

    //! textmacro GetKeyArray takes name
        static key $name$_BASE

        static constant integer $name$ = Math.Integer.MIN + Memory.IntegerKeys.Array.OFFSET + $name$_BASE * Memory.IntegerKeys.Array.SIZE
    //! endtextmacro


    You get unique ids in constant distances, so the ids between can be treated as part of a coherent array. The first index, which you gain by GetKeyArray, is the root key you pass to the header and stores up to which index the array holds data.

    The code below is an example for a shared memory that can be implemented by other structs that want to use it.


    Requires:
    Code
    • Structfollowers
    • some basic globals

      Code (vJASS):
      //! runtextmacro Folder("BasicConstants")
                globals
                    constant integer STRUCT_MAX = 8190
                    constant integer STRUCT_MIN = 1

                    constant integer STRUCT_BASE = STRUCT_MAX + 1
                    constant integer STRUCT_EMPTY = STRUCT_MIN - 1

                    constant integer NULL = STRUCT_EMPTY
                endglobals
            endscope

    • some maths

      Code (vJASS):
      //! runtextmacro Folder("Math")
                //! runtextmacro Struct("Integer")
                    static integer MIN = -2147483645
                endstruct
            endscope

            //! runtextmacro StaticStruct("Math")
                //! runtextmacro LinkToStaticStruct("Math", "Integer")

                static method RandomI takes integer lowBound, integer highBound returns integer
                    return GetRandomInt(lowBound, highBound)
                endmethod
            endstruct

    • CreateSimpleAddState (that's my standard textmacro for creating simple abstract numeric values as struct members)

      Code (vJASS):
      //! textmacro CreateSimpleAddState takes type, defaultValue
                $type$ value

                method Get takes nothing returns $type$
                    return this.value
                endmethod

                method Set takes $type$ value returns nothing
                    set this.value = value
                endmethod

                method Add takes $type$ value returns nothing
                    call this.Set(this.Get() + value)
                endmethod

                method Start takes nothing returns nothing
                    call this.Set($defaultValue$)
                endmethod

                method Subtract takes $type$ value returns nothing
                    call this.Set(this.Get() - value)
                endmethod
            //! endtextmacro

    • Wrappers for GameCache and HashTable (not shown here because not important)


    Head:

    Code
    Code (vJASS):
    //! runtextmacro Folder("Memory")
        //! runtextmacro Folder("IntegerKeys")
            //! runtextmacro Struct("Array")
                static constant integer EMPTY = -1
                static constant integer OFFSET = 8192
                static constant integer SIZE = 8192  //you can have up to SIZE - 1 values in an array, that would fit with the normal max amount of instances of a struct
                static constant integer STARTED = 0  //the first index holds the amount of elements

                //! textmacro Memory_IntegerKeys_Array_CreateType takes name, type, bugConverter
                    static method Count$name$s takes integer parentKey, integer key returns integer
                        return (thistype.EMPTY + Memory.IntegerKeys.GetInteger(parentKey, key))
                    endmethod

                    static method Count$name$sByHandle takes handle handleSource, integer key returns integer
                        return thistype.Count$name$s(GetHandleId(handleSource), key)
                    endmethod

                    static method Get$name$ takes integer parentKey, integer key, integer index returns $type$
                        return Memory.IntegerKeys.Get$name$(parentKey, key + thistype.EMPTY + index + 2)
                    endmethod

                    static method Get$name$ByHandle takes handle handleSource, integer key, integer index returns $type$
                        return thistype.Get$name$(GetHandleId(handleSource), key, index)
                    endmethod

                    static method Contains$name$ takes integer parentKey, integer key, $type$ value returns boolean
                        local integer iteration = Count$name$s(parentKey, key)

                        loop
                            exitwhen (iteration < thistype.STARTED)

                            exitwhen (Get$name$(parentKey, key, iteration) == value)

                            set iteration = iteration - 1
                        endloop

                        if (iteration < thistype.STARTED) then
                            return false
                        endif

                        return true
                    endmethod

                    static method Add$name$ takes integer parentKey, integer key, $type$ value returns boolean
                        local integer count = Count$name$s(parentKey, key) + 1

                        call Memory.IntegerKeys.SetInteger(parentKey, key, count - thistype.EMPTY)

                        call Memory.IntegerKeys.Set$name$(parentKey, key + thistype.EMPTY + count + 2, value)

                        return (count == thistype.STARTED)
                    endmethod

                    static method Add$name$ByHandle takes handle handleSource, integer key, $type$ value returns boolean
                        return thistype.Add$name$(GetHandleId(handleSource), key, value)
                    endmethod

                    static method Remove$name$ takes integer parentKey, integer key, $type$ value returns boolean
                        local integer count = Count$name$s(parentKey, key)

                        local integer iteration = count

                        loop
    debug                        exitwhen (iteration < thistype.STARTED)

                            exitwhen (Get$name$(parentKey, key, iteration) == value)

                            set iteration = iteration - 1
                        endloop

    debug                    if (iteration < thistype.STARTED) then

    debug                        call BJDebugMsg("Failed to remove "+$BugConverter$(value)+" from array "+I2S(key)+" of parentKey "+I2S(parentKey)+" ("+I2S(count)+")")

    debug                    else
                        call Memory.IntegerKeys.Set$name$(parentKey, key + thistype.EMPTY + iteration + 2, Get$name$(parentKey, key, count))

                        set count = count - 1

                        call Memory.IntegerKeys.SetInteger(parentKey, key, count - thistype.EMPTY)
    debug                    endif

                        return (count == thistype.EMPTY)
                    endmethod

                    static method Remove$name$ByHandle takes handle handleSource, integer key, $type$ value returns boolean
                        return thistype.Remove$name$(GetHandleId(handleSource), key, value)
                    endmethod

                    static method Random$name$ takes integer parentKey, integer key, integer lowerBound, integer higherBound returns $type$
                        return thistype.Get$name$(parentKey, key, Math.RandomI(lowerBound, higherBound))
                    endmethod

                    static method Random$name$ByHandle takes handle handleSource, integer key, integer lowerBound, integer higherBound returns $type$
                        return thistype.Random$name$(GetHandleId(handleSource), key, lowerBound, higherBound)
                    endmethod

                    static method Random$name$All takes integer parentKey, integer key returns $type$
                        return thistype.Random$name$(parentKey, key, thistype.STARTED, Count$name$s(parentKey, key))
                    endmethod
                //! endtextmacro

                //! runtextmacro Memory_IntegerKeys_Array_CreateType("Boolean", "boolean", "B2S")
                //! runtextmacro Memory_IntegerKeys_Array_CreateType("Integer", "integer", "I2S")
                //! runtextmacro Memory_IntegerKeys_Array_CreateType("Real", "real", "R2S")
                //! runtextmacro Memory_IntegerKeys_Array_CreateType("String", "string", "")
            endstruct
        endscope

        //! runtextmacro Struct("IntegerKeys")
            static HashTable CACHE

            //! runtextmacro LinkToStruct("IntegerKeys", "Array")

            static method RemoveChild takes integer parentKey returns nothing
                call CACHE.RemoveMission(parentKey)
            endmethod

            //! textmacro Memory_IntegerKeys_CreateType takes name, type
                static method Set$name$ takes integer parentKey, integer key, $type$ value returns nothing
                    call CACHE.$name$.Set(parentKey, key, value)
                endmethod

                static method Set$name$ByHandle takes handle handleSource, integer key, $type$ value returns nothing
                    call thistype.Set$name$(GetHandleId(handleSource), key, value)
                endmethod

                static method Remove$name$ takes integer parentKey, integer key returns nothing
                    call CACHE.$name$.Remove(parentKey, key)
                endmethod

                static method Remove$name$ByHandle takes handle handleSource, integer key returns nothing
                    call thistype.Remove$name$(GetHandleId(handleSource), key)
                endmethod

                ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

                static method Get$name$ takes integer handleSource, integer key returns $type$
                    return CACHE.$name$.Get(handleSource, key)
                endmethod

                static method Get$name$ByHandle takes handle handleSource, integer key returns $type$
                    return thistype.Get$name$(GetHandleId(handleSource), key)
                endmethod
            //! endtextmacro

            //! runtextmacro Memory_IntegerKeys_CreateType("Boolean", "boolean")
            //! runtextmacro Memory_IntegerKeys_CreateType("Integer", "integer")
            //! runtextmacro Memory_IntegerKeys_CreateType("Real", "real")
            //! runtextmacro Memory_IntegerKeys_CreateType("String", "string")

            static method Init takes nothing returns nothing
                set CACHE = HashTable.Create()
            endmethod
        endstruct

        //! runtextmacro Folder("StringKeys")
            //! runtextmacro Struct("Array")
                static constant integer EMPTY = -1
                static constant integer STARTED = 0

                //! textmacro Memory_StringKeys_Array_CreateType takes name, type, bugConverter
                    static method Count$name$s takes string parentKey, string key returns integer
                        return (thistype.EMPTY + Memory.StringKeys.GetInteger(parentKey, key))
                    endmethod

                    static method Get$name$ takes string parentKey, string key, integer index returns $type$
                        return Memory.StringKeys.Get$name$(parentKey, key + I2S(thistype.EMPTY + index + 2))
                    endmethod

                    static method Contains$name$ takes string parentKey, string key, $type$ value returns boolean
                        local integer iteration = Count$name$s(parentKey, key)

                        loop
                            exitwhen (iteration < thistype.STARTED)

                            exitwhen (Get$name$(parentKey, key, iteration) == value)

                            set iteration = iteration - 1
                        endloop

                        if (iteration < thistype.STARTED) then
                            return false
                        endif

                        return true
                    endmethod

                    static method Add$name$ takes string parentKey, string key, $type$ value returns boolean
                        local integer count = Count$name$s(parentKey, key) + 1

                        call Memory.StringKeys.SetInteger(parentKey, key, count - thistype.EMPTY)

                        call Memory.StringKeys.Set$name$(parentKey, key + I2S(thistype.EMPTY + count + 2), value)

                        return (count == thistype.STARTED)
                    endmethod

                    static method Remove$name$ takes string parentKey, string key, $type$ value returns boolean
                        local integer count = Count$name$s(parentKey, key)

                        local integer iteration = count

                        loop
    debug                        exitwhen (iteration < thistype.STARTED)

                            exitwhen (Get$name$(parentKey, key, iteration) == value)

                            set iteration = iteration - 1
                        endloop

    debug                    if (iteration < thistype.STARTED) then

    debug                        call BJDebugMsg("Failed to remove "+$BugConverter$(value)+" from array "+key+" of parentKey "+parentKey+" ("+I2S(count)+")")

    debug                    else
                        call Memory.StringKeys.Set$name$(parentKey, key + I2S(thistype.EMPTY + iteration + 2), Get$name$(parentKey, key, count))

                        set count = count - 1

                        call Memory.StringKeys.SetInteger(parentKey, key, count)
    debug                    endif

                        return (count == thistype.EMPTY)
                    endmethod

                    static method Random$name$ takes string parentKey, string key returns $type$
                        return thistype.Get$name$(parentKey, key, Math.RandomI(thistype.STARTED, Count$name$s(parentKey, key)))
                    endmethod
                //! endtextmacro

                //! runtextmacro Memory_StringKeys_Array_CreateType("Boolean", "boolean", "B2S")
                //! runtextmacro Memory_StringKeys_Array_CreateType("Integer", "integer", "I2S")
                //! runtextmacro Memory_StringKeys_Array_CreateType("Real", "real", "R2S")
                //! runtextmacro Memory_StringKeys_Array_CreateType("String", "string", "")
            endstruct
        endscope

        //! runtextmacro Struct("StringKeys")
            static GameCache CACHE

            //! runtextmacro LinkToStruct("StringKeys", "Array")

            static method RemoveChild takes string parentKey returns nothing
                call CACHE.RemoveMission(parentKey)
            endmethod

            //! textmacro Memory_StringKeys_CreateType takes name, type
                static method Set$name$ takes string parentKey, string key, $type$ value returns nothing
                    call CACHE.$name$.Set(parentKey, key, value)
                endmethod

                static method Remove$name$ takes string parentKey, string key returns nothing
                    call CACHE.$name$.Remove(parentKey, key)
                endmethod

                static method Get$name$ takes string parentKey, string key returns $type$
                    return CACHE.$name$.Get(parentKey, key)
                endmethod
            //! endtextmacro

            //! runtextmacro Memory_StringKeys_CreateType("Boolean", "boolean")
            //! runtextmacro Memory_StringKeys_CreateType("Integer", "integer")
            //! runtextmacro Memory_StringKeys_CreateType("Real", "real")
            //! runtextmacro Memory_StringKeys_CreateType("String", "string")

            static method Init takes nothing returns nothing
                set CACHE = GameCache.Create("blub")
            endmethod
        endstruct
    endscope

    //! runtextmacro StaticStruct("Memory")
        //! runtextmacro LinkToStaticStruct("Memory", "IntegerKeys")
        //! runtextmacro LinkToStaticStruct("Memory", "StringKeys")

        static method Init takes nothing returns nothing
            call IntegerKeys.Init()
            call StringKeys.Init()
        endmethod
    endstruct


    For implementation:

    Code (vJASS):
    //! textmacro Data_Implement takes baseType
        method Destroy takes nothing returns nothing
            call Memory.IntegerKeys.RemoveChild($baseType$(this).Id.Get())
        endmethod
    //! endtextmacro

    //! textmacro Data_Type_Implement takes baseType, whichTypeName, whichType
        method Get takes integer key returns $whichType$
            return Memory.IntegerKeys.Get$whichTypeName$($baseType$(this).Id.Get(), key)
        endmethod

        method Is takes integer key returns boolean
            return (this.Get(key) != HASH_TABLE.$whichTypeName$.DEFAULT_VALUE)
        endmethod

        method Remove takes integer key returns nothing
            call Memory.IntegerKeys.Remove$whichTypeName$($baseType$(this).Id.Get(), key)
        endmethod

        method Set takes integer key, $whichType$ value returns nothing
            call Memory.IntegerKeys.Set$whichTypeName$($baseType$(this).Id.Get(), key, value)
        endmethod
    //! endtextmacro

    //! textmacro Data_Type_Array_Implement takes baseType, whichTypeName, whichType
        method Contains takes integer key, $whichType$ value returns boolean
            return Memory.IntegerKeys.Array.Contains$whichTypeName$($baseType$(this).Id.Get(), key, value)
        endmethod

        method Count takes integer key returns integer
            return Memory.IntegerKeys.Array.Count$whichTypeName$s($baseType$(this).Id.Get(), key)
        endmethod

        method Get takes integer key, integer index returns $whichType$
            return Memory.IntegerKeys.Array.Get$whichTypeName$($baseType$(this).Id.Get(), key, index)
        endmethod

        method Clear takes integer key returns nothing
            call Memory.IntegerKeys.Array.Clear($baseType$(this).Id.Get(), key)
        endmethod

        method Remove takes integer key, $whichType$ value returns boolean
            return Memory.IntegerKeys.Array.Remove$whichTypeName$($baseType$(this).Id.Get(), key, value)
        endmethod

        method RemoveSorted takes integer key, $whichType$ value returns boolean
            return Memory.IntegerKeys.Array.RemoveSorted$whichTypeName$($baseType$(this).Id.Get(), key, value)
        endmethod

        method Add takes integer key, $whichType$ value returns boolean
            return Memory.IntegerKeys.Array.Add$whichTypeName$($baseType$(this).Id.Get(), key, value)
        endmethod

        method AddSorted takes integer key, $whichType$ value returns boolean
            return Memory.IntegerKeys.Array.AddSorted$whichTypeName$($baseType$(this).Id.Get(), key, value)
        endmethod

        method Random takes integer key, integer lowerBound, integer higherBound returns $whichType$
            return Memory.IntegerKeys.Array.Random$whichTypeName$($baseType$(this).Id.Get(), key, lowerBound, higherBound)
        endmethod

        method RandomAll takes integer key returns $whichType$
            return this.Random(key, Memory.IntegerKeys.Array.STARTED, this.Count(key))
        endmethod
    //! endtextmacro

    //additional

    //! textmacro Data_Boolean_Implement takes baseType
        method Add takes integer key returns boolean
            local boolean oldValue = this.Get(key)

            call this.Set(key, HASH_TABLE.Boolean.DEFAULT_VALUE == false)

            return (oldValue == HASH_TABLE.Boolean.DEFAULT_VALUE)
        endmethod

        method Subtract takes integer key returns boolean
            local boolean oldValue = this.Get(key)

            call this.Set(key, HASH_TABLE.Boolean.DEFAULT_VALUE)

            return (oldValue != HASH_TABLE.Boolean.DEFAULT_VALUE)
        endmethod
    //! endtextmacro

    //! textmacro Data_Integer_Implement takes baseType
        method Contains takes integer key returns boolean
            return (this.Get(key) > HASH_TABLE.Integer.DEFAULT_VALUE)
        endmethod

        method Add takes integer key, integer value returns boolean
            local integer oldValue = this.Get(key)

            call this.Set(key, oldValue + value)

            if (oldValue != HASH_TABLE.Integer.DEFAULT_VALUE) then
                return false
            endif

            return (value != HASH_TABLE.Integer.DEFAULT_VALUE)
        endmethod

        method Subtract takes integer key, integer value returns boolean
            local integer oldValue = this.Get(key)

            set value = (oldValue - value)

            call this.Set(key, value)

            if (oldValue == HASH_TABLE.Integer.DEFAULT_VALUE) then
                return false
            endif

            return (value == HASH_TABLE.Integer.DEFAULT_VALUE)
        endmethod
    //! endtextmacro

    //! textmacro Data_Real_Implement takes baseType
        method Add takes integer key, real value returns boolean
            local real oldValue = this.Get(key)

            call this.Set(key, oldValue + value)

            if (oldValue != HASH_TABLE.Real.DEFAULT_VALUE) then
                return false
            endif

            return (value != HASH_TABLE.Real.DEFAULT_VALUE)
        endmethod

        method Subtract takes integer key, real value returns boolean
            local real oldValue = this.Get(key)

            set value = (oldValue - value)

            call this.Set(key, value)

            if (oldValue == HASH_TABLE.Real.DEFAULT_VALUE) then
                return false
            endif

            return (value == HASH_TABLE.Real.DEFAULT_VALUE)
        endmethod
    //! endtextmacro

    //! textmacro Data_String_Implement takes baseType
        method Add takes integer key, string value returns boolean
            local string oldValue = this.Get(key)

            call this.Set(key, oldValue + value)

            if (oldValue != HASH_TABLE.String.DEFAULT_VALUE) then
                return false
            endif

            return (value != HASH_TABLE.String.DEFAULT_VALUE)
        endmethod

        method Subtract takes integer key, real value returns boolean
            local string oldValue = this.Get(key)

            set value = (oldValue - value)

            call this.Set(key, value)

            if (oldValue == HASH_TABLE.String.DEFAULT_VALUE) then
                return false
            endif

            return (value == HASH_TABLE.String.DEFAULT_VALUE)
        endmethod
    //! endtextmacro

    //for string keys

    //! textmacro Data_StringKey_Implement
        static method Destroy takes string whichString returns nothing
            call Memory.StringKeys.RemoveChild(whichString)
        endmethod
    //! endtextmacro

    //! textmacro Data_StringKey_Type_Implement takes whichTypeName, whichType
        static method Get takes string whichString, integer key returns $whichType$
            return Memory.StringKeys.Get$whichTypeName$(whichString, Integer.ToString(key))
        endmethod

        static method Remove takes string whichString, integer key returns nothing
            call Memory.StringKeys.Remove$whichTypeName$(whichString, Integer.ToString(key))
        endmethod

        static method Set takes string whichString, integer key, $whichType$ value returns nothing
            call Memory.StringKeys.Set$whichTypeName$(whichString, Integer.ToString(key), value)
        endmethod
    //! endtextmacro

    //! textmacro Data_StringKey_Type_Array_Implement takes whichTypeName, whichType
        static method Count takes string whichString, integer key returns integer
            return Memory.StringKeys.Array.Count$whichTypeName$s(whichString, Integer.ToString(key))
        endmethod

        static method Get takes string whichString, integer key, integer index returns $whichType$
            return Memory.StringKeys.Array.Get$whichTypeName$(whichString, Integer.ToString(key), index)
        endmethod

        static method Remove takes string whichString, integer key, $whichType$ value returns boolean
            return Memory.StringKeys.Array.Remove$whichTypeName$(whichString, Integer.ToString(key), value)
        endmethod

        static method Add takes string whichString, integer key, $whichType$ value returns boolean
            return Memory.StringKeys.Array.Add$whichTypeName$(whichString, Integer.ToString(key), value)
        endmethod

        static method Random takes string whichString, integer key, integer lowerBound, integer higherBound returns $whichType$
            return Memory.StringKeys.Array.Random$whichTypeName$(whichString, Integer.ToString(key), lowerBound, higherBound)
        endmethod

        static method RandomAll takes string whichString, integer key returns $whichType$
            return thistype.Random(whichString, key, Memory.IntegerKeys.Array.STARTED, thistype.Count(whichString, key))
        endmethod
    //! endtextmacro


    Here you get unique keys for the memory:

    Code (vJASS):
    //! textmacro GetKey takes name
        static key $name$_BASE

        static constant integer $name$ = Math.Integer.MIN + $name$_BASE
    //! endtextmacro

    //! textmacro GetKeyArray takes name
        static key $name$_BASE

        static constant integer $name$ = Math.Integer.MIN + Memory.IntegerKeys.Array.OFFSET + $name$_BASE * Memory.IntegerKeys.Array.SIZE
    //! endtextmacro


    Actually, you could forget GetKey and instead always take GetKeyArray since the base key vJass provides gets blown either way but I think that's semantically tidier.


    Implementation:

    code
    The following shows how it is implemented in a struct, so this struct automatically gets a parentkey and you can easily store data belonging to it.

    Macros:

    Example on Unit:

    Code (vJASS):
    //! runtextmacro Folder("Unit")
        //! runtextmacro Folder("Data")
            //! runtextmacro Struct("Boolean")
                //! runtextmacro Data_Type_Implement("Unit", "Boolean", "boolean")
            endstruct

            //! runtextmacro Folder("Integer")
                //! runtextmacro Struct("Array")
                    //! runtextmacro Data_Type_Array_Implement("Unit", "Integer", "integer")
                endstruct
            endscope

            //! runtextmacro Struct("Integer")
                //! runtextmacro LinkToStruct("Integer", "Array")

                //! runtextmacro Data_Type_Implement("Unit", "Integer", "integer")
            endstruct
        endscope

        //! runtextmacro Struct("Data")
            //! runtextmacro LinkToStruct("Data", "Boolean")
            //! runtextmacro LinkToStruct("Data", "Integer")

            //! runtextmacro Data_Implement("Unit")
        endstruct

        //! runtextmacro Struct("Id")
            //! runtextmacro GetKeyArray("KEY_ARRAY")

            //! runtextmacro CreateSimpleAddState("integer", "KEY_ARRAY + this")
        endstruct
    endscope

    //! runtextmacro BaseStruct("Unit", "UNIT")
        //! runtextmacro LinkToStruct("Unit", "Data")
        //! runtextmacro LinkToStruct("Unit", "Id")

        static method Create takes <params> returns thistype
            local unit self = <unit>
            local thistype this = thistype.allocate()

            set this.self = self

            call this.Id.Start()  //must be called to equip the unit with its parentkey for the memory

            return this
        endmethod
    endstruct


    Call:

    code
    When you now want to use it:

    Code (vJASS):
    struct IceCream
        //! runtextmacro GetKey("KEY")
        //! runtextmacro GetKeyArray("SCOOP_KEY_ARRAY")

        Waffle base

        method AddToUnit takes Unit whichUnit returns nothing
            call whichUnit.Data.Integer.Set(KEY, this)
        endmethod

        method AddScoop takes IceCreamType whichType returns nothing
            call this.Data.Integer.Array.Add(SCOOP_KEY_ARRAY, whichType)
        endmethod

        static method Create takes nothing returns thistype
            local thistype this = thistype.allocate()

            set this.base = Waffle.Create()

            return this
        endmethod
    endstruct
     
    Last edited: Apr 15, 2011
  2. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    What the hell.

    Do matrix math and you can get n dimensions based on each dimension size limited by 2^32/2 (unless you want to check for negatives like ARGB, which would yield 2^32 at the cost of more than double overhead of 2^32/2).

    dimension*size+dimension2

    where dimension2 < size

    where dimension*size+dimension2 < 2^32/2

    This can be used to craft a lot of dimensions

    ((dimension*size+dimension2)*size2+dimension3)*size3+dimension4

    etc

    You can split the dimensions into two keys (take advantage of hashtable having two dimensions), although this shouldn't be done as then the instances can't be passed around.

    I don't get why you have all of this extra complexity... furthermore, the dimension sizes really vary depending on what a person is trying to accomplish... I've used 91, 16, 8192, etc. One I've used was [8192][8192][16].

    Matrix math in the programming world is used to create multi dimensional arrays. Arrays storing pointers to other arrays = jagged arrays.

    jagged
    Code (Text):

    int[][] numArray = new int[][] { new int[] {1,3,5}, new int[] {2,4,6,8,10} };
     
    multidimensional
    Code (Text):

    int[,] numbers = { {1, 2}, {3, 4}, {5, 6} };
     
     
  3. WaterKnight

    WaterKnight

    Joined:
    Aug 18, 2009
    Messages:
    4,035
    Resources:
    5
    Maps:
    1
    Tutorials:
    4
    Resources:
    5
    Of course you can implement more dimensions. I just said it was common to have a one-dimensional for an object.