Snippet Linked List

Trollvottel

never aging title
Reaction score
262
I think we dont have one, so i decided to make a standart list implementation.
Description etc in the Code comment (yes my english is horrible).

Code:
JASS:

//===============================================================================
// LINKED LIST 
//===========by Trollvottel======================================================
// DESCRIPTION:
//  * Creates a dynamic data structure.
//  * It consists of a front and an end dummy node, data are attached to nodes between them
//    which are linked together (each node has a previous and a next node
//    like nodes in a chain). 
//  * Nodes can be replaced or removed,  you can add nodes between existing
//    nodes.
//  * At the moment you can store 3 different data types: integers, reals, strings
//  * The amount of code created by importing this library is about the same as 360 lines vJass 
//    code.
//  * You can only store 8190 "objects" of one type at one time.
//================================================================================
// PURPOSE:
//  * Making easy data handling possible
//  * Making code more structured
//  * Making code more overlookable
//================================================================================
// USAGE:
//    1. Linked_IntList
//    2. Linked_RealList
//    3. Linked_StringList
//  * All of these have the same methods.
//  * You will work with a position pointer which points to a node in the list to call methods on it
//
//=================================================================================================
//  * METHOD SUMMARY:
//          RETURN VALUES:            
//          1. $ create () : thistype
//              -> creates a new List and returns it
//-------------------------------------------------------------------------------------------------
//          2.   isEmpty () : boolean
//              -> if there are no things stored in the list, this will return true
//-------------------------------------------------------------------------------------------------
//          3.   isInFrontOf () : boolean
//              -> if the position pointer points to the front node (is in front of the list)
//                 this will return true
//-------------------------------------------------------------------------------------------------
//          4.   isBehind () : boolean
//              -> if the position pointer points to the end node (is behind the list)
//                 this will return true
//-------------------------------------------------------------------------------------------------
//          5.   getItem () : $TYPE$
//              -> returns the object stored in the node the position pointer is pointing to
//=================================================================================================
//          ACTIONS (Conditions are what the user should care for):
//          1.  next () : nothing
//              Condition: the pointer is not at the end node
//              -> moves the position pointer to the next node
//-------------------------------------------------------------------------------------------------
//          2. previous () : nothing
//              Condition: the pointer is not at the front node
//              -> moves the position pointer to the previous node
//-------------------------------------------------------------------------------------------------
//          3. toFirst () : nothing
//              -> moves the position pointer to the next of the front node
//-------------------------------------------------------------------------------------------------
//          4. toLast () : nothing
//              -> moves the position pointer to the previous of the end node
//-------------------------------------------------------------------------------------------------
//          5. replace ($TYPE$ cont) : nothing
//              Condition: the position pointer is not pointing to the end node or front node.
//              -> replaces the object stored at the node the position pointer is pointing to
//-------------------------------------------------------------------------------------------------
//          6. insertInFrontOf ($TYPE$ cont) : nothing
//              Conditon: the position pointer is not pointing to the front node
//              -> inserts the object in front of the node the position pointer is pointing to
//-------------------------------------------------------------------------------------------------
//          7. insertBehind ($TYPE$ cont) : nothing
//              Conditon: the position pointer is not pointing to the end node
//              -> inserts the object behind the node the position pointer is pointing to
//-------------------------------------------------------------------------------------------------
//          8. remove () : nothing
//              Condition: the position pointer is not pointing to the end node or front node
//              -> removes the node the position pointer is pointing to and points to the next node
//-------------------------------------------------------------------------------------------------
//          9. addList ($NAME$List which) : nothing
//              -> adds another list to the end of the current list. the list you add will be cleared
//-------------------------------------------------------------------------------------------------
//          10. destroy () : nothing
//              -> destroys the list and all it's nodes
//-------------------------------------------------------------------------------------------------
//          11. flush () : nothing
//              -> empties the list and destroys all nodes in it
//==================================================================================================
//          ATTRIBUTES:
//          1.  size : integer
//              -> Number of elements/nodes in your list
//==================================================================================================
// Library Code - You better dont touch... You better dont look... Who cares about the implementation?
library Linked
        
    //! textmacro_once Linked_List_create takes TYPE, NAME, NULL
    private struct $NAME$Node
      
        thistype next
        thistype prev
        
        $TYPE$ cont
        
        static method create takes $TYPE$ content, thistype p, thistype n returns thistype
            local thistype this = .allocate()
            
            debug if integer(this) == 0 then
            debug   call BJDebugMsg("Could not create $NAME$Node, too many instances!")            
            debug   return 0
            debug endif
            
            set .next = n
            set .prev = p
            set .cont = content
            return this
        endmethod
        
        method onDestroy takes nothing returns nothing
            set .cont = $NULL$
        endmethod
    endstruct
    
    public struct $NAME$List
    
        readonly integer size = 0
        
        private $NAME$Node front
        private $NAME$Node end
        private $NAME$Node position
    
        static method create takes nothing returns thistype
            local thistype this = .allocate()
            
            debug if integer(this) == 0 then
            debug   call BJDebugMsg("Could not create $NAME$List, too many instances!")            
            debug   return 0
            debug endif
            
            set .front = $NAME$Node.create($NULL$, 0, 0)
            set .end = $NAME$Node.create($NULL$, .front, 0)
            set .front.next = .end
            set .position = .front
            return this
        endmethod
    
        method isEmpty takes nothing returns boolean
            return .size == 0
        endmethod
        
        method isInFrontOf takes nothing returns boolean
            return .position == .front
        endmethod
        
        method isBehind takes nothing returns boolean
            return .position == .end
        endmethod
        
        method next takes nothing returns nothing
            debug if .position == .end then
            debug   call BJDebugMsg("$NAME$List: Tried to get next of end node!")
            debug   return 
            debug endif
            set .position = .position.next
        endmethod
                
        method previous takes nothing returns nothing
            debug if .position == .front then
            debug   call BJDebugMsg("$NAME$List: Tried to get previous of front node!")
            debug   return 
            debug endif
            set .position = .position.prev
        endmethod

        
        method toFirst takes nothing returns nothing
            set .position = .front.next
        endmethod
        
        method toLast takes nothing returns nothing
            set .position = .end.prev
        endmethod
        
        method getItem takes nothing returns $TYPE$
            debug if .position == .front or .position == .end then
            debug   call BJDebugMsg("$NAME$List: Tried to get content of front or end node!")
            debug   return $NULL$
            debug endif
            return .position.cont
        endmethod
        
        method replace takes $TYPE$ cont returns nothing
            debug if .position == .front or .position == .end then
            debug   call BJDebugMsg("$NAME$List: Tried to replace content of front or end node!")
            debug   return 
            debug endif
            set .position.cont = cont
        endmethod
        
        method insertInFrontOf takes $TYPE$ cont returns nothing
            local $NAME$Node tmp = $NAME$Node.create(cont, .position.prev, .position)
            
            debug if .position == .front then
            debug   call BJDebugMsg("$NAME$List: Tried to insert in front of front node!")
            debug   return 
            debug endif
            
            set .size = .size + 1
            set .position.prev.next = tmp
			set .position.prev = tmp
        endmethod
        
        method insertBehind takes $TYPE$ cont returns nothing
            local $NAME$Node tmp = $NAME$Node.create(cont, .position, .position.next)
            
            debug if  .position == .end then
            debug   call BJDebugMsg("$NAME$List: Tried to insert behind end node!")
            debug   return 
            debug endif            
            
            set .size = .size + 1
            set .position.next.prev = tmp
			set .position.next = tmp
        endmethod
        
        method remove takes nothing returns nothing
            
            debug if .position == .front or .position == .end then
            debug   call BJDebugMsg("$NAME$List: Tried to remove front or end node!")
            debug   return 
            debug endif
            
            set .size = .size - 1
            set .position.next.prev = .position.prev
			set .position.prev.next = .position.next
            call .position.destroy()
			set .position = .position.next
        endmethod
        
        method flush takes nothing returns nothing
            call .toFirst()
            loop
                exitwhen .isEmpty()
                call .remove()            
            endloop
        endmethod
        
        stub method addList takes $NAME$List which returns nothing
            local $NAME$Node tmp = .end
            local $NAME$Node tmp2 = which.front
            
            if which.isEmpty() == false then
                set .end.prev.next = which.front.next
                set .end.prev.next.prev = .end.prev
                
                set .end = which.end
                
                set which.end = tmp
                
                set tmp.prev = tmp2
                set tmp2.next = tmp
                
                set .size = .size + which.size
                set which.size = 0
                
            debug else
            debug   call BJDebugMsg("$NAME$List: Added empty list!")
            endif
            
        endmethod
        
        method onDestroy takes nothing returns nothing
            call .flush()
            call .front.destroy()
            call .end.destroy()
        endmethod
        
    endstruct

//! endtextmacro

//! runtextmacro Linked_List_create("integer", "Int", "0")
//! runtextmacro Linked_List_create("real", "Real", "0.0")
//! runtextmacro Linked_List_create("string", "String", "null")


endlibrary

Example of usage:
JASS:
scope ListExample




function Trig_ListTest_Actions takes nothing returns nothing
    local Linked_IntList l = Linked_IntList.create() // creates the list. the position pointer points
                                                     // to the front node
       call l.insertBehind(5) // insert a node with the given value behind the position pointer
    call l.next()  // move to the last added node
       call l.insertBehind(4)
    call l.next()  
       call l.insertBehind(3)
    call l.next()  
       call l.insertBehind(2)
    call l.next()  
       call l.insertBehind(1)
    

    call l.toFirst()
    
    loop
        exitwhen l.isBehind()
        
        call BJDebugMsg(I2S(l.getItem()))
        call l.next()
        // Displays 5 \n 4 \n 3 \n 2 \n 1 where \n is a new line
    endloop
endfunction

//===========================================================================
function InitTrig_ListExample takes nothing returns nothing
    set gg_trg_ListExample = CreateTrigger(  )
    call TriggerAddAction( gg_trg_ListExample, function Trig_ListTest_Actions )
    call TriggerRegisterTimerEvent(gg_trg_ListExample, 0.5, false)
endfunction

endscope
As you may have noticed, there is no type safe handle listing. do you think i should add some feature to do it which would increase the amount of code?
 

Azlier

Old World Ghost
Reaction score
461
I don't think so, really. .next should return the next instance. .prev (not .previous) should return the previous instance. And the contents should be called something like data.

In fact, .next and .prev shouldn't even be methods. They should be everyday struct members.

And, this should be a module.
 

Trollvottel

never aging title
Reaction score
262
and why should it be like this?

next and previous do not return the next instance because these methods just move the positon pointer. if i would return the next node that would not be good for anything since you shall not be able to access any of its members.

>They should be everyday struct members.

they are struct members. members of the NODES and not of the List itself.


>And, this should be a module.

why?
 

Azlier

Old World Ghost
Reaction score
461
Because a module lets it be anything you want it to be.

JASS:
struct IntList
    integer cont
    implement Linked_List
endstruct


>they are struct members. members of the NODES and not of the List itself.

A list and a node should not be two different things. A list is merely a node with more nodes attached to it.
 

Trollvottel

never aging title
Reaction score
262
why?
So, textmacro is unneeded.

its uneeded for the user.

well, JassHelper really should support typification :/

@azlier:


>A list and a node should not be two different things. A list is merely a node with more nodes attached to it.

A node is one part, a List is the whole thing. so in my opinion the list should not be just one part of the whole linked to the rest...
 

Jesus4Lyf

Good Idea™
Reaction score
397
I think we dont have one, so i decided to make a standart list implementation.
You were wrong! XD We have a very nice implementation.
JASS:
// Library Code - You better dont touch... You better dont look... Who cares about the implementation?
"DON'T READ MY LIB!"
And that's all she wrote.
But I have to say,
That I care for the code.

Actually, the other implementation is nicer I think. But I suppose more to the point, the other one is approved also. Graveyarded (we already have this). ^^
 

Trollvottel

never aging title
Reaction score
262
You were wrong! XD We have a very nice implementation.

"DON'T READ MY LIB!"
And that's all she wrote.
But I have to say,
That I care for the code.

Actually, the other implementation is nicer I think. But I suppose more to the point, the other one is approved also. Graveyarded (we already have this). ^^

1.nice poem ^^.
2. thats your opinion, but its just a different interface (mine is more dynamic and has more functions i think) and my system doesnt make the things it stores lists.
3.so i come to the conclusion that "we already have this" isnt really an argument. also, look at TT and KT2 which are both approved and have almost the same interface/purpose.
 

Azlier

Old World Ghost
Reaction score
461
KT does a totally different thing than TT. The interfaces just happen to be similar. And they both use timers.

>mine is more dynamic and has more functions i think

...More dynamic?
 

Trollvottel

never aging title
Reaction score
262
>KT does a totally different thing than TT.

So whats the difference in the purpose?

> ...More dynamic?

In some points, yes. And you dont have to create a new struct for everything you want to store, each time like a textmacro run. (well i dont really know how the modules work, but i guess its just copying the code of the module into the struct)
 
Reaction score
341
(well i dont really know how the modules work, but i guess its just copying the code of the module into the struct)

I think vex said that modules are like textmacro's so I'm guessing your right.
 

Jesus4Lyf

Good Idea™
Reaction score
397
>So whats the difference in the purpose?
KT2 allows you to specify whatever period you like, and is more efficient in execution than TT.

If you look at the code, to support this, it is a big change. ;)

On topic:
JASS:
//! runtextmacro Linked_List_create("handle", "Handle", "null")

How is a "handle" list useful? You can't typecast handles as far as I know (without return nothing bug).

I see and appreciate what you are trying to do here, but the extra array read using a struct adds is useful for code maintainability. How often does one need a list of real values, and if they did why wouldn't they code this themself at the time...

Usually it would be something like "damage to be dealt" in a list of reals, lets say. And very soon the user is going to go "oh, I need to know to or from which unit the damage is dealt"... And your system does not support this. The module does. :)

The above is only an example (I'm not saying that's the only thing you could use this to do).
 

Trollvottel

never aging title
Reaction score
262
So you think removing everything but int (and string) list would make sense since ints can store structs and so they could store handles aswell?
 

Azlier

Old World Ghost
Reaction score
461
Ah, but you can use [lJASS]GetHandleId[/lJASS]. You now have a slower, crappier integer list!
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top