• 🏆 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Snippet] BufferEx

I was in need of something to make messages in Warcraft III pop out Type-writer style, and that would require a Buffer. And since I had some other things that needed to use a buffer (Like a Unit order queue and an AI-Action/Behavior system), I decided that I needed to make them run off of one Buffer system. Hence, I wrote this.

The reason I called it BufferEx is because Nestharus' Save/Load system uses a library called Buffer which can be found in the Small Code Snippets thread.

Code

JASS:
/**********************************
*
*   BufferEx
*   v1.0.0.1
*   By Magtheridon96
*
*   - Data structure resource.
*     This buffer is a FIFO (First in,
*     First out) data structure. 
*     What you write first is read
*     first.
*
*   Optional Requirement:
*   ---------------------
*
*       - Table by Bribe
*           - hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
*
*   API:
*   ----
*
*       struct BufferEx extends array
*
*           static method create takes nothing returns thistype
*               - Creates a new buffer.
*
*           method read takes nothing returns integer
*           method write takes integer i returns nothing
*               - Data IO functions.
*
*           method operator empty takes nothing returns boolean
*               - Determines whether the buffer is empty or not.
*
*           method operator count takes nothing returns integer
*               - Determines the amount of data left to read.
*
*           method clear takes nothing returns nothing
*           method reset takes nothing returns nothing
*               - Clear all data in the buffer.
*
*           method destroy takes nothing returns nothing
*               - Destroy the buffer.
*
**********************************/
library BufferEx requires optional Table

    globals
        /*
        *   An empty buffer will be cleaned if it has more
        *   than THRESHOLD slots of unneeded data.
        *   This needs to be less than 8192.
        *   The smaller, the better.
        *   Do not make it too small though.
        *   Too Small = 10, 15, etc...
        *
        *   We might as well clear the Buffer whenever possible,
        *   but that would be incredibly inefficient if a user
        *   is going to write, then read, then write, then read
        *   every single time. A threshold will minimize the 
        *   number of times we are going to clear a Buffer.
        */
        private constant integer THRESHOLD = 32
    endglobals
    
    struct BufferEx extends array
        private static integer array rn
        private static integer ic = 0
        
        static if LIBRARY_Table then
            private static Table array data
        else
            private static hashtable data = InitHashtable()
        endif
        
        private static integer array readIndex
        private static integer array writeIndex
        
        static method create takes nothing returns thistype
            /*
            *    Allocate struct instance.
            */
            local thistype this = rn[0]
            if this == 0 then
                set ic = ic + 1
                set this = ic
            else
                set rn[0] = rn[this]
            endif
            
            /*
            *    If the table is null, we create
            *    it. I'm not destroying any tables.
            *    I'm only flushing them when a
            *    Buffer is destroyed.
            */
            static if LIBRARY_Table then
                if data[this] == 0 then
                    set data[this] = Table.create()
                endif
            endif
            
            return this
        endmethod
        
        method operator empty takes nothing returns boolean
            return readIndex[this] == writeIndex[this]
        endmethod
        
        method operator count takes nothing returns integer
            return writeIndex[this] - readIndex[this]
        endmethod
        
        method clear takes nothing returns nothing
            /*
            *    Reset the write index and the read index
            *    and clear all the data in the buffer.
            */
            set writeIndex[this] = 0
            set readIndex[this] = 0
            
            static if LIBRARY_Table then
                call data[this].flush()
            else
                call FlushChildHashtable(data, this)
            endif
        endmethod
        
        method read takes nothing returns integer
            local integer value
            
            /*
            *    We will only read from the buffer
            *    if it actually has data in it.
            */
            if not this.empty then
                set readIndex[this] = readIndex[this] + 1
                
                static if LIBRARY_Table then
                    set value = data[this][readIndex[this]]
                else
                    set value = LoadInteger(data, this, readIndex[this])
                endif
                
                if this.empty and readIndex[this] >= THRESHOLD then
                    call this.clear()
                endif
                
                return value
            debug else
                debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "ATTEMPTED TO READ FROM EMPTY BUFFER.")
            endif
            
            return 0
        endmethod
        
        method write takes integer i returns nothing
            /*
            *    We write the data.
            */
            set writeIndex[this] = writeIndex[this] + 1
            
            static if LIBRARY_Table then
                set data[this][writeIndex[this]] = i
            else
                call SaveInteger(data, this, writeIndex[this], i)
            endif
        endmethod
        
        method reset takes nothing returns nothing
            call this.clear()
        endmethod
        
        method destroy takes nothing returns nothing
            /*
            *    Deallocate struct instance.
            */
            set rn[this] = rn[0]
            set rn[0] = this
            
            call this.clear()
        endmethod
    endstruct
    
endlibrary

Demo

JASS:
struct Test extends array

    static BufferEx myBuffer
    
    private static method printStr takes string s returns nothing
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, s)
    endmethod
    
    private static method wait takes real time returns nothing
        call TriggerSleepAction(time)
    endmethod
    
    private static method onInit takes nothing returns nothing
        local integer index = 0
        local integer array data
        local boolean failure = false
        
        set myBuffer = BufferEx.create()
        
        set data[0] = 100
        set data[1] = 242
        set data[2] = 214
        set data[3] = 245
        set data[4] = 935
        set data[5] = 652
        
        loop
            call myBuffer.write(data[index])
            exitwhen index == 5
            set index = index + 1
        endloop
        
        set index = 0
        
        loop
            if myBuffer.read() != data[index] then
                set failure = true
            endif
            exitwhen index == 5
            set index = index + 1
        endloop
        
        if not failure then
            call printStr("Buffer Write Test 1 Successful")
        else
            call printStr("Buffer Write Test 1 Failed")
            return
        endif
        
        call wait(1)
        
        call myBuffer.clear()
        if myBuffer.empty then
            call printStr("Buffer Clear Test 1 Successful")
        else
            call printStr("Buffer Clear Test 1 Failed")
            return
        endif
        
        call wait(1)
        
        call myBuffer.write(4)
        call myBuffer.write(5)
        call myBuffer.write(9)
        call myBuffer.write(7)
        
        if myBuffer.read() == 4 then
            if myBuffer.read() == 5 then
                if myBuffer.read() == 9 then
                    if myBuffer.read() == 7 then
                        call printStr("Buffer Write Test 2 Successful")
                    else
                        call printStr("Buffer Write Test 2 Failed")
                    endif
                else
                    call printStr("Buffer Write Test 2 Failed")
                endif
            else
                call printStr("Buffer Write Test 2 Failed")
            endif
        else
            call printStr("Buffer Write Test 2 Failed")
        endif
        
        call wait(1)
        
        call myBuffer.clear()
        if myBuffer.empty then
            call printStr("Buffer Clear Test 2 Successful")
        else
            call printStr("Buffer Clear Test 2 Failed")
        endif
        
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        call myBuffer.write(1)
        
        call wait(1)
        
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        call myBuffer.read()
        
        call wait(1)
        
        if myBuffer.empty then
            call printStr("Clear Test Successful.")
        else
            call printStr("Clear Test Failed.")
        endif
    endmethod

endstruct

Feel free to comment.
 
Last edited:
Top