[Snippet] BufferEx

Scripts

13 years
edited 8 years
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 at the Hive Workshop.

Code

Code (jass) Select
/**********************************
*
*   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
*           - https://wc3modding.info/4611/snippet-new-table/
*
*   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

Code (jass) Select
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.
13 years
I like the code and the style. Approved