1. A slave to two rhythms, the 22nd Terraining Contest is here.
    Dismiss Notice
  2. The heavens smile on the old faithful. The 16th Techtree Contest has begun.
    Dismiss Notice
  3. The die is cast - the 6th Melee Mapping Contest results have been announced. Onward to the Hive Cup!
    Dismiss Notice
  4. The glory of the 20th Icon Contest is yours for the taking!
    Dismiss Notice
  5. Shoot to thrill, play to kill. Sate your hunger with the 33rd Modeling Contest!
    Dismiss Notice
  6. Do you hear boss music? It's the 17th Mini Mapping Contest!
    Dismiss Notice
  7. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

[Snippet] StringIterator

Discussion in 'JASS Resources' started by edo494, Dec 29, 2013.

  1. edo494

    edo494

    Joined:
    Apr 16, 2012
    Messages:
    3,846
    Resources:
    5
    Spells:
    1
    JASS:
    4
    Resources:
    5
    pretty simple, wrote in under hour, but I wanted to share this piece for anyone that does something like I did with chat modes and dont want to write 100 additional lines of code

    Code (vJASS):

    library StringIterator
    /*
        Made by: edo494
        Version: 1.0
       
        Description:
           
            This piece of code allows you to forward iterate over words in strings,
            reading them out from the "container" depending on the delimiter.
           
        API:
           
            struct StringIterator
               
                static method create takes string container returns thistype
                    - creates new instance
                   
                method setDelims takes string delimiters returns nothing
                    - sets the delimiters to characters in "delimiters"
                    - example: "abc" will make the instance treat any
                      a, b or c inside the string as delimiter
                     
                method read takes nothing returns string
                    - returns string containing charaters from "position"
                      up to "end" or until any delimiter is found
                     
                method peek takes nothing returns string
                    - returns string containing charaters from "position"
                      up to "end" or until any delimiter is found
                    - does not move "position" forward
                   
                method nextDelim takes nothing returns string
                    - returns upcomming delimiter pack
                    - so if 2 or more delimiters after each other occur
                      this function returns all of them
                     
                method operator string= takes string newContainer returns nothing
                    - sets internal container to "newContainer"
                    - call to this function resets position
                     
                method operator start takes nothing returns boolean
                    - returns whether the iterator is at the start or not
                   
                method operator end takes nothing returns boolean
                    - returns whether the iterator is at the end or not
                   
                method operator size takes nothing returns integer
                    - returns number of charaters inside the container
               
                method operator position takes nothing returns integer
                    - returns the current position of the iterator inside container
                   
                method operator position= takes integer newPos returns boolean
                    - sets the position to the "newPos"
                    - in debug mode, if <0 or >size, returns false
                      otherwise true
                    - outside of debug mode, returns true
                   
                method reset takes nothing returns nothing
                    - returns the iterator to start
                   
    */

        struct StringIterator
            private string myStr
            private string myDelims
            private integer pointer
            private integer sSize
            private integer dSize
           
            static method create takes string s returns thistype
                local thistype this = allocate()
                set this.myStr = s
                set this.myDelims = " "
                set this.pointer = 0
                set this.dSize = StringLength(this.myDelims)
                set this.sSize = StringLength(s)
                return this
            endmethod

            static method createEx takes string container, string delims returns thistype
                local thistype this = allocate()
                set this.myStr = container
                set this.myDelims = delims
                set this.pointer = 0
                set this.dSize = StringLength(delims)
                set this.sSize = StringLength(container)
                return this
            endmethod
           
            method setDelims takes string s returns nothing
                set this.myDelims = s
                set this.dSize = StringLength(s)
            endmethod
           
            method operator start takes nothing returns boolean
                return this.pointer <= 0
            endmethod
           
            method operator end takes nothing returns boolean
                return this.pointer >= this.sSize
            endmethod
           
            method operator size takes nothing returns integer
                return this.sSize
            endmethod
           
            method operator position takes nothing returns integer
                return this.pointer
            endmethod
           
            private method isDelim takes string s returns boolean
                local integer i = this.dSize
                local string delims = this.myDelims
                if s == null then
                    return true
                endif
                loop
                    exitwhen i == 0
                    if s == SubString(delims, i-1, i) then
                        return true
                    endif
                    set i = i - 1
                endloop
                return false
            endmethod
           
            private method readBool takes boolean b returns string
                local string helper = ""
                local string ths = this.myStr
                local integer size = this.sSize
                local integer current = this.pointer
                local string cont = ""
                //evade all remaining delimiters from the last read
                loop
                    if current == size then
                        exitwhen true
                    endif
                    exitwhen not isDelim(SubString(ths, current, current+1))
                    set current = current + 1
                endloop
                //fill up the string
                loop
                    exitwhen current == size
                    set helper = SubString(ths, current, current+1)
                    exitwhen isDelim(helper)
                    set cont = cont + helper
                    set current = current + 1
                endloop
                if b then
                    set this.pointer = current
                endif
                //return the string
                return cont
            endmethod
           
            method read takes nothing returns string
                return readBool(true)
            endmethod
           
            method peek takes nothing returns string
                return readBool(false)
            endmethod
           
            method nextDelim takes nothing returns string
                local string ths = this.myStr
                local integer size = this.sSize
                local integer current = this.pointer
                local string s = ""
                local string q = ""
                if current == size then
                    return ""
                endif
                //evade all non delimiters
                loop
                    set q = SubString(ths, current, current+1)
                    exitwhen current == size or not isDelim(q)
                    set current = current + 1
                endloop
                //read next delimiters
                loop
                    set q = SubString(ths, current, current+1)
                    exitwhen current == size or not isDelim(q)
                    set s = s + q
                    set current = current + 1
                endloop
                //return them
                return s
            endmethod
           
            method operator position= takes integer newPosition returns boolean
                debug if newPosition > this.size or newPosition < 0 then
                    debug return false
                debug endif
                set this.pointer = newPosition
                return true
            endmethod
           
            method reset takes nothing returns nothing
                set this.pointer = 0
            endmethod
           
            method operator string= takes string s returns nothing
                set this.myStr = s
                set this.sSize = StringLength(s)
                set this.pointer = 0
            endmethod
        endstruct
    endlibrary
     


    Example:

    Code (vJASS):

    scope example initializer init
       
        private function t takes nothing returns boolean
            local string s = GetEventPlayerChatString()
            local StringIterator iter = StringIterator.create(s)
            call iter.setDelims(" ")
            call BJDebugMsg("Message inserted by player:\n")
            loop
                exitwhen iter.end
                call BJDebugMsg(iter.read())
            endloop
            return false
        endfunction
       
        private function init takes nothing returns nothing
            local trigger tr = CreateTrigger()
            call TriggerRegisterPlayerChatEvent(tr, Player(0), "", false)
            call TriggerAddCondition(tr, Condition(function t))
            set tr = null
        endfunction
    endscope
     
     
    Last edited: Jan 6, 2014
  2. Cokemonkey11

    Cokemonkey11

    Wurst Reviewer

    Joined:
    May 9, 2006
    Messages:
    3,270
    Resources:
    18
    Tools:
    1
    Maps:
    5
    Spells:
    3
    Tutorials:
    2
    JASS:
    7
    Resources:
    18
    I didn't check the code in detail, but nothing jumps out at me as bad. API is nice. I suggest approval.
     
  3. edo494

    edo494

    Joined:
    Apr 16, 2012
    Messages:
    3,846
    Resources:
    5
    Spells:
    1
    JASS:
    4
    Resources:
    5
    Updated

    • create now initializes delimiter list to " " instead of " -"
    • new method: static createEx(string container, string delimiters) returns thistype
     
  4. TriggerHappy

    TriggerHappy

    Code Moderator

    Joined:
    Jun 23, 2007
    Messages:
    3,789
    Resources:
    22
    Spells:
    11
    Tutorials:
    2
    JASS:
    9
    Resources:
    22
    Approved.