Snippet String Parser

Nestharus

o-o
Reaction score
84
Why did I make this?
Because I couldn't find a plain old string parser like this one on TH : (

What does the demo map have?
The parser + typeof + converter demonstration

Just input a list of stuff like [ljass]"1 5 'hpea' hello false oh"[/ljass] and watch it spew out all of the values you entered plus their types. When the createByType is on, you can enter [ljass]"1 5'hpea'hellofalseoh"[/ljass] to get the same results.

plans
Making ripType faster by adding internal push = P.
Adding string delimiters " " (this will allow you to group characters up)
Adding escape character \
Adding createType (create new types like colors)
Adding addAlias (add a new alies to a type, like red or blue to colors or on/off to booleans)
Making toString return a string and building the string as the stack is created

changelog
1.1.1.0
added stringType operator for String Stack, which returns the data type of the string on the node. Use stringType instead of typeof on nodes as it will be faster.

node stringTypes are only auto set on type ripping and create by type as the types are already found.

When a node does not have a type set to it, it will have a type set to it the first type stringType is accessed.

Updated demo to use stringType instead of typeof.
1.1.0.1
Fixed a small bug in createByType
1.1.0.0
Made rip faster and fixed possible bugs, also made it so that all things have to be consecutive.

Added ripType, which rips a stack of values of a type, like all integers in a string.

Added toString, which converts a stack into a string with a delimiter.

Made typeof faster.

Added StringStack.createByType, which allows you to split a string up by delimiter and type.. very very very useful!! Made it have some decently smart parsing for when it detects a new type as well to make it a bit faster.

with delimiter of " "
+1.1+1-1'hpea'hellotrue hi

outputs

+ 1.1 + 1 -1 'hpea' hello true hi
1.0.3.5
made parser loop faster
1.0.3.4
Made parser handle delimiter as first characters properly
1.0.3.3
Made StringStack parser a bit better (now correctly handles masses of delimiter characters that are placed next to each other)
1.0.3.2
Made typof recognize values with negative flags as integers/reals
1.0.3.1
Optimized create a bit
1.0.3.0
added createSingle for creating a stack with one node in it. Useful if you just want a string that isn't split up without complicating up an API.
1.0.2.1
added DELIMITER global at top to make setting ARG_DELIMITER easier
1.0.2.0
added StringType.compare
1.0.1.0
Added FilterString
1.0.0.1
Had introduced a new field to StringStack called count but had forgotten about a local called count in the constructor

JASS:
library StringParser uses Ascii
//Ascii- thehelper.net/forums/showthread.php?t=135066
globals
    //what StringStack.ARG_DELIMITER is set to
    private constant string DELIMITER = " "
endglobals

////////////////////////////////////////////////////////////////////////
//Version: 1.1.1.0
//Author: Nestharus
//
//Description
//      StringParser allows you to easily-
//          1. Split strings into a stack of substrings given a delimiter
//                  Given delimiter of " "
//                      "hi ho 1 53" -> "hi", "ho", "1", "53"
//
//          2. Infer primitive type of a string (null, boolean, ascii int, integer, real, string)
//                  "12345" would be of type integer
//
//          3. Rip values of specific primitive type out of a string that are in order
//                  ripping integers from asdf243dsfk35 would return 243
//
//          4. Easily convert between primitive types and strings where no native conversion exists
//                  Ascii converter ('hpea' -> "hpea" -> 'hpea')
//                  Boolean converter (false -> "false" -> false)
////////////////////////////////////////////////////////////////////////
//API
//      function FilterString takes string stringToFilter, string char, boolean onlyAtStart returns string
//          Filters a character out of the string. If onlyAtStart is true,
//          will filter until it runs into a character of a different type.  
//
//      struct StringStack extends array
//          Used to create a stack of strings
//
//          public static constant string ARG_DELIMITER
//              Specifies map delimiter for splitting strings into substrings
//              Can be used if you want your strings to follow map specifications.
//
//          readonly StringStack next
//              Retrieves the next string on the stack (returns the node)
//
//          readonly string value
//              The substring string value stored in the node
//
//          readonly integer count
//              How many strings are on the stack
//
//          readonly integer stringType
//              The type of value the string contains. Use this instead of typeof when dealing with
//              a String Stack.
//
//          method toString takes string delimiter returns string
//              Gets the entire string value of the stack (all of the stack values in string form)
//
//          static method createSingle takes string val returns thistype
//              Creates a single node that holds the string val
//
//          static method create takes string val, string delimiter returns StringStack
//              Parses a string into a stack of strings
//              Strings split into substrings based on the delimiter
//
//          static method createByType takes string val, string delimiter returns thistype
//              Splits a string by type and by delimiter
//
//          public method pop takes nothing returns thistype
//              Pops off the first node of the string stack. Useful 
//              for iteration as the stack's instance is its first node.
//
//              Demo-
//                  set node = node.pop()        
//
//          public method destroy takes nothing returns nothing
//              Destroys the stack
//
//      struct StringType
//          Used for handling string conversions to types 
//          (null, boolean, ascii int, integer, real, string)
//
//              constant integer NULL
//              constant integer BOOLEAN
//              constant integer ASCII
//              constant integer INTEGER
//              constant integer REAL
//              constant integer STRING
//
//              static method operator [] takes integer t returns string
//                  Returns type name given type id
//                  
//                  Demo-
//                      StringType[StringType.NULL] would return "null"
//
//              static method S2B takes string val returns boolean
//                  Converts string to boolean ("false" converts to false)
//
//              static method S2A takes string val returns integer
//                  Converts ascii string to integer ("'hpea'" converts to 'hpea')
//
//              static method B2S takes boolean val returns string
//                  Converts boolean to string (false converts to "false")
//
//              static method A2S takes integer val returns string
//                  Converts ascii integer to string ('hpea' converts to "'hpea'")
//
//              static method compare takes integer type1, integer type2 returns boolean
//                  Checks to see if type1 can typecast to type2
//                  All integers can go to strings, but not all strings can go to integers
//
//              static method typeof takes string val returns integer
//                  Infers the type of a string ("1234" would be type INTEGER)
//
//              static method rip takes string val, integer typeToRip returns string
//                  Rips out a single value of type from string (cannot be segmented)
//
//                  Demo-
//                      Ripping INTEGER from "ah3gfs4gq2fm329" would give 3
//                      Ripping BOOLEAN from "trufaletrafalse" would return false
//                      Ripping ASCII from "ds'faadsfksags'hpea'" would give 'hpea'
//
//              static method ripType takes string val, integer typeToRip returns StringStack
//                  Rips out all values of a given type from string
////////////////////////////////////////////////////////////////////////
    private keyword advCreate
    private keyword advCreateSingle
    
    function FilterString takes string stringToFilter, string char, boolean onlyAtStart returns string
        local integer count = 0
        local integer length = StringLength(stringToFilter)
        local string newString = ""
        local string charCheck
        if (onlyAtStart) then
            loop
                exitwhen SubString(stringToFilter, count, count+1) != char
                set count = count + 1
            endloop
            set newString = SubString(stringToFilter, count, length)
        else
            loop
                exitwhen count == length
                set charCheck = SubString(stringToFilter, count, count+1)
                if (charCheck != char) then
                    set newString = newString + charCheck
                endif
                set count = count + 1
            endloop
        endif
        
        return newString
    endfunction
    
    private function Typeof takes string val returns integer
        local integer length
        local string char
        local integer curType = StringType.NULL
        local string boolChecker
        local boolean foundDecimal
        local boolean foundNeg
        local boolean foundInt
        
        //make sure not null
        if (val != null) then
            set curType = StringType.BOOLEAN
            //check to see if boolean
            set boolChecker = StringCase(val, false)
            if (boolChecker != "true" and boolChecker != "false") then
                set length = StringLength(val)
                set curType = StringType.ASCII
                
                //check to see if ascii integer
                if ((length != 3 and length != 6) or SubString(val, 0, 1) != "'" or SubString(val, length-1, length) != "'") then
                    set curType = StringType.INTEGER
                    
                    //if curType can't be determined at this point, have to parse it
                    set foundDecimal = false
                    set foundNeg = false
                    set foundInt = false
                    loop
                        exitwhen length == 0
                        set char = SubString(val, length-1, length)
                        if (foundNeg or (char != "0" and char != "1" and char != "2" and char != "3" and char != "4" and char != "5" and char != "6" and char != "7" and char != "8" and char != "9")) then
                            if (not foundNeg) then
                                if (char == "-" and foundInt) then
                                    set foundNeg = true
                                elseif (char == "." and not foundDecimal) then
                                    set curType = StringType.REAL
                                    set foundDecimal = true
                                else
                                    return StringType.STRING
                                endif
                            else
                                return StringType.STRING //no more parsing necessary
                            endif
                        else
                            set foundInt = true
                        endif
                        set length = length - 1
                    endloop
                endif
            endif
        endif
        return curType
    endfunction
    
    struct StringStack extends array
        public static constant string ARG_DELIMITER = DELIMITER
        
        private thistype nextX
        private string valueX
        private integer countX
        private integer stringTypeX
        
        private static integer instanceCount = 0
        private static integer array recycle
        private static integer recycleCount = 0
        
        public method operator stringType takes nothing returns integer
            if (stringTypeX == -1) then
                set stringTypeX = Typeof(valueX)
            endif
            return stringTypeX
        endmethod
        
        private method operator stringType= takes integer val returns nothing
            set stringTypeX = val
        endmethod
        
        public method operator next takes nothing returns thistype
            return nextX
        endmethod
        
        private method operator next= takes integer i returns nothing
            set nextX = i
        endmethod
        
        public method operator value takes nothing returns string
            return valueX
        endmethod
        
        private method operator value= takes string s returns nothing
            set valueX = s
        endmethod
        
        public method operator count takes nothing returns integer
            return countX
        endmethod
        
        private method operator count= takes integer c returns nothing
            set countX = c
        endmethod
        
        public method toString takes string delimiter returns string
            local string s = null
            loop
                exitwhen this == 0
                if (value != null and value != delimiter and value != "") then
                    if (s == null) then
                        set s = value
                    else
                        set s = s + delimiter + value
                    endif
                endif
                set this = next
            endloop
            return s
        endmethod
        
        public static method createByType takes string val, string delimiter returns thistype
            local thistype this = 0
            local thistype first = 0
            local string char
            local integer length
            local integer start //start of substring
            local integer subLength //end of substring
            local integer curType
            local boolean foundNeg
            local boolean foundDec
            local boolean foundInt
            
            local integer nextLength
            local integer nextType
            local thistype last = 0
            local integer count = 0
            
            if (val != null and val != "") then
                set length = StringLength(val)
                set subLength = 0 //parse forward so types inferred correctly
                                  //.10323.103 would be wrong if parsed backwards 
                                  //(. 10323.103 instead of .10323 .103)
                                  //reason to use checkLength instead of subLength is because check might not
                                  //include sub
                                  
                set nextLength = 0
                set nextType = 0
                loop
                    if (nextType != 0) then
                        set curType = nextType
                        set start = subLength
                        set subLength = nextLength
                        set nextType = 0
                    else
                        set curType = 0 //reset current type
                    endif
                    if (curType == 0 or curType == StringType.INTEGER or curType == StringType.REAL or curType == StringType.STRING) then
                        loop
                            exitwhen subLength == length //if subLength is length, string is done
                            set subLength = subLength + 1
                            //if there is no current type, infer type
                            set char = SubString(val, subLength-1, subLength)
                            if (char != delimiter) then
                                if (curType == 0) then
                                    set start = subLength-1
                                    //check to see if it is a boolean
                                    if (start+4 <= length and StringCase(SubString(val, start, start+4), false) == "true") then
                                        set subLength = start + 4
                                        set curType = StringType.BOOLEAN
                                        exitwhen true //exit immediately since character group
                                    elseif (start+5 <= length and StringCase(SubString(val, start, start+5), false) == "false") then
                                        set subLength = start + 5
                                        set curType = StringType.BOOLEAN
                                        exitwhen true //exit immediately since character group
                                    //check to see if it is ascii
                                    elseif (char == "'") then //either ascii or string
                                        if (start+3 <= length) then
                                            if (SubString(val, start+2, start+3) == "'") then
                                                set subLength = start + 3
                                                set curType = StringType.ASCII
                                                exitwhen true
                                            elseif (start+6 <= length and SubString(val, start+5, start+6) == "'") then
                                                set subLength = start + 6
                                                set curType = StringType.ASCII
                                                exitwhen true
                                            else //string
                                                set curType = StringType.STRING
                                            endif
                                        else //string
                                            set curType = StringType.STRING
                                        endif
                                    else
                                        //infer char
                                        if (subLength+1 <= length) then
                                            if (char == ".") then
                                                set foundDec = true
                                                set foundNeg = false
                                                set foundInt = false
                                                set curType = StringType.REAL //can upgrade to string if it finds no integers
                                            elseif (char == "-") then
                                                set foundNeg = true
                                                set foundDec = false
                                                set foundInt = false
                                                set curType = StringType.INTEGER //can upgrade to real
                                            endif
                                        endif
                                        if (curType == 0 and (char == "0" or char == "1" or char == "2" or char == "3" or char == "4" or char == "5" or char == "6" or char == "7" or char == "8" or char == "9")) then
                                            set curType = StringType.INTEGER //can upgrade to real
                                            set foundInt = true
                                            set foundDec = false
                                            set foundNeg = false
                                        endif
                                        
                                        if (curType == 0) then
                                            set curType = StringType.STRING
                                        endif
                                    endif
                                else
                                    if (curType == StringType.INTEGER or curType == StringType.REAL) then
                                        if (char != "0" and char != "1" and char != "2" and char != "3" and char != "4" and char != "5" and char != "6" and char != "7" and char != "8" and char != "9") then
                                            if (char == "-" and not foundNeg and not foundInt and not foundDec) then
                                                if (curType == 0) then
                                                    set curType = StringType.INTEGER
                                                endif
                                                set foundNeg = true
                                            elseif (char == "." and not foundDec) then //upgrade integer to real
                                                set curType = StringType.REAL
                                                set foundDec = true
                                            elseif (not foundInt) then //upgrade integer/real to string
                                                set curType = StringType.STRING
                                            else
                                                set subLength = subLength-1 //chop off last char
                                                exitwhen true //done parsing integer/real
                                            endif
                                        else
                                            set foundInt = true
                                            if (curType == 0) then
                                                set curType = StringType.INTEGER
                                            endif
                                        endif
                                    endif
                                endif
                                if (curType == StringType.STRING) then
                                    //strings needs to check all types
                                    if (subLength+3 <= length and StringCase(SubString(val, subLength-1, subLength+3), false) == "true") then
                                        set nextLength = subLength+3
                                        set nextType = StringType.BOOLEAN
                                        set subLength = subLength - 1
                                        exitwhen true
                                    elseif (subLength+4 <= length and StringCase(SubString(val, subLength-1, subLength+4), false) == "false") then
                                        set nextLength = subLength+4
                                        set nextType = StringType.BOOLEAN
                                        set subLength = subLength - 1
                                        exitwhen true
                                    elseif (char == "'" and subLength+2 <= length) then 
                                        if (SubString(val, subLength+1, subLength+2) == "'") then
                                            set nextLength = subLength+2
                                            set nextType = StringType.ASCII
                                            set subLength = subLength - 1
                                            exitwhen true
                                        elseif (subLength+5 <= length and SubString(val, subLength+4, subLength+5) == "'") then
                                            set nextLength = subLength+5
                                            set nextType = StringType.ASCII
                                            set subLength = subLength - 1
                                            exitwhen true
                                        endif
                                    else
                                        if (subLength+1 <= length and char == "-") then
                                            set char = SubString(val, subLength, subLength+1)
                                            set foundNeg = true
                                            set nextLength = subLength
                                            set nextType = StringType.INTEGER
                                            if (subLength+2 <= length and char == ".") then
                                                set nextLength = nextLength + 1
                                                set char = SubString(val, subLength+1, subLength+2)
                                                set foundDec = true
                                                set nextType = StringType.REAL
                                            else
                                                set foundDec = false
                                            endif
                                        elseif (subLength+1 <= length and char == ".") then
                                            set nextLength = subLength
                                            set nextType = StringType.REAL
                                            set foundDec = true
                                            set foundNeg = false
                                            set char = SubString(val, subLength, subLength+1)
                                        endif
                                        if (char == "0" or char == "1" or char == "2" or char == "3" or char == "4" or char == "5" or char == "6" or char == "7" or char == "8" or char == "9") then
                                            set foundInt = true
                                            if (nextType == 0) then
                                                set nextType = StringType.INTEGER
                                                set nextLength = subLength
                                                set foundNeg = false
                                                set foundDec = false
                                            else
                                                set nextLength = nextLength + 1
                                            endif
                                            set subLength = subLength - 1
                                            exitwhen true
                                        else
                                            set nextType = 0
                                        endif
                                    endif
                                endif
                            elseif (curType != 0) then
                                set subLength = subLength-1
                                exitwhen true
                            endif
                        endloop
                    endif
                    
                    exitwhen curType == 0
                    if (recycleCount != 0) then
                        set recycleCount = recycleCount - 1
                        set this = recycle[recycleCount]
                    else
                        set instanceCount = instanceCount + 1
                        set this = instanceCount
                    endif
                    set count = count + 1
                    
                    if (first == 0) then
                        set first = this
                        set last = this
                    else
                        set last.next = this
                        set last = this
                    endif
                    set next = 0
                    set this.stringType = curType
                    
                    set value = SubString(val, start, subLength)
                endloop
                
                set last = first
                loop
                    exitwhen last == 0
                    set last.count = count
                    set count = count - 1
                    set last = last.next
                endloop
            endif
            
            return first
        endmethod
        
        //creates a stack of strings given a delimiter
        public static method create takes string val, string delimiter returns thistype
            local thistype this = 0
            local thistype first = 0
            local integer count
            local string char
            local integer length
            local boolean found
            
            if (val != null and val != "") then
                set length = StringLength(val)
                set count = length
                loop
                    exitwhen count == 0
                    set found = false
                    set length = count
                    loop
                        set count = count - 1
                        set char = SubString(val, count, count + 1)
                        if (char != delimiter and not found) then
                            set found = true
                            set length = count+1
                        endif
                        exitwhen count == 0 or (char == delimiter and found)
                    endloop
                    
                    exitwhen not found
                    if (recycleCount != 0) then
                        set recycleCount = recycleCount - 1
                        set this = recycle[recycleCount]
                    else
                        set instanceCount = instanceCount + 1
                        set this = instanceCount
                    endif
                    
                    set next = first
                    set this.count = first.count+1
                    set first = this
                    set stringType = -1
                    
                    if (count != 0) then
                        set value = SubString(val, count+1, length)
                    else
                        set value = SubString(val, 0, length)
                    endif
                endloop
            endif
            
            return this
        endmethod
        
        public static method advCreate takes string val, string delimiter, integer stringType returns thistype
            local thistype this = 0
            local thistype first = 0
            local integer count
            local string char
            local integer length
            local boolean found
            
            if (val != null and val != "") then
                set length = StringLength(val)
                set count = length
                loop
                    exitwhen count == 0
                    set found = false
                    set length = count
                    loop
                        set count = count - 1
                        set char = SubString(val, count, count + 1)
                        if (char != delimiter and not found) then
                            set found = true
                            set length = count+1
                        endif
                        exitwhen count == 0 or (char == delimiter and found)
                    endloop
                    
                    exitwhen not found
                    if (recycleCount != 0) then
                        set recycleCount = recycleCount - 1
                        set this = recycle[recycleCount]
                    else
                        set instanceCount = instanceCount + 1
                        set this = instanceCount
                    endif
                    
                    set next = first
                    set this.count = first.count+1
                    set first = this
                    
                    if (count != 0) then
                        set value = SubString(val, count+1, length)
                    else
                        set value = SubString(val, 0, length)
                    endif
                    
                    set this.stringType = stringType
                endloop
            endif
            
            return this
        endmethod
        
        public static method createSingle takes string val returns thistype
            local thistype this
            if (recycleCount != 0) then
                set recycleCount = recycleCount - 1
                set this = recycle[recycleCount]
            else
                set instanceCount = instanceCount + 1
                set this = instanceCount
            endif
            
            set next = 0
            set this.count = 1
            set value = val
            set this.stringType = -1
            
            return this
        endmethod
        
        public static method advCreateSingle takes string val, integer stringType returns thistype
            local thistype this
            if (recycleCount != 0) then
                set recycleCount = recycleCount - 1
                set this = recycle[recycleCount]
            else
                set instanceCount = instanceCount + 1
                set this = instanceCount
            endif
            
            set next = 0
            set this.count = 1
            set value = val
            set this.stringType = stringType
            
            return this
        endmethod
        
        public method pop takes nothing returns thistype
            set recycle[recycleCount] = this
            set recycleCount = recycleCount + 1
            return next
        endmethod
        
        public method destroy takes nothing returns nothing
            loop
                exitwhen this == 0
                set recycle[recycleCount] = this
                set recycleCount = recycleCount + 1
                set this = next
            endloop
        endmethod
    endstruct
    
    struct StringType extends array
        private static string array typeNames
        public static constant integer NULL = 0
        public static constant integer BOOLEAN = 1
        public static constant integer ASCII = 2
        public static constant integer INTEGER = 3
        public static constant integer REAL = 4
        public static constant integer STRING = 5
        
        public static method operator [] takes integer t returns string
            return typeNames[t]
        endmethod
        
        //string to boolean
        public static method S2B takes string val returns boolean
            if (val == "true") then
                return true
            endif
            return false
        endmethod
        
        //string to ascii
        public static method S2A takes string val returns integer
            local integer i = 0
            local integer digit
            if (val != null) then
                set digit = StringLength(val)-2
                set val = SubString(val, 1, digit+1)
                loop
                    exitwhen digit == 0
                    set digit = digit - 1
                    set i = i * 128 + Char2Ascii(SubString(val, digit, digit+1))
                endloop
            endif
            
            return i
        endmethod
        
        //boolean to string
        public static method B2S takes boolean val returns string
            if (val) then
                return "true"
            endif
            return "false"
        endmethod
        
        //ascii to string
        public static method A2S takes integer val returns string
            local string ascii = "'"
            loop
                exitwhen val == 0
                set ascii = ascii + Ascii2Char(val - val/128*128)
                set val = val / 128
            endloop
            
            return ascii + "'"
        endmethod
        
        public static method compare takes integer type1, integer type2 returns boolean
            return type1 == type2 or (type1 > ASCII and type2 > ASCII and type1 < type2)
        endmethod
        
        public static method typeof takes string val returns integer
            return Typeof(val)
        endmethod
        
        //rips out a single argument given a type
        //slow but extremely flexible
        public static method rip takes string val, integer typeToRip returns string
            local string arg = ""
            local integer length
            local integer count
            local string char
            local integer argLength
            local integer boolCount
            local boolean foundDecimal
            local boolean foundInt
            local integer start
            local boolean foundNegative
            
            if (val != null) then
                set length = StringLength(val)
                set count = 0
                
                //rip null, which is easy, lol
                if (typeToRip == StringType.NULL) then
                    set arg = null
                //rip boolean, which tries to piece together straight** chars that could build boolean
                elseif (typeToRip == StringType.BOOLEAN) then
                    set count = 4
                    set arg = null
                    if (count <= length) then
                        loop
                            //check for true
                            set arg = SubString(val, count-4, count)
                            if (arg != "true") then
                                set arg = null
                                set count = count + 1
                                exitwhen count > length
                                set arg = SubString(val, count-5, count)
                                if (arg != "false") then
                                    set arg = null
                                    set count = count + 1
                                    exitwhen count > length
                                endif
                            endif
                            exitwhen arg != null
                        endloop
                    endif
                //rip out an ascii value
                elseif (typeToRip == StringType.ASCII) then
                    set count = 3
                    if (count <= length) then
                        loop
                            set arg = SubString(val, count-3, count)
                            if (SubString(arg, 0, 1) != "'" or SubString(arg, 2, 3) != "'") then
                                set arg = null
                                exitwhen count+3 > length
                                set arg = SubString(val, count-3, count+3)
                                if (SubString(arg, 0, 1) != "'" or SubString(arg, 5, 6) != "'") then
                                    set arg = null
                                    set count = count + 1
                                    exitwhen count > length
                                endif
                            endif
                            exitwhen arg != null
                        endloop
                    endif
                //rips out a plain old integer
                elseif (typeToRip == StringType.INTEGER) then
                    set foundInt = false
                    set count = 0
                    set foundNegative = false
                    loop
                        exitwhen count == length
                        set char = SubString(val, count, count+1)
                        if (char == "-" and not foundInt) then
                            set start = count
                            set foundNegative = true
                        elseif (char == "0" or char == "1" or char == "2" or char == "3" or char == "4" or char == "5" or char == "6" or char == "7" or char == "8" or char == "9") then
                            if (not foundNegative and not foundInt) then
                                set start = count
                            endif
                            set foundInt = true
                        elseif (foundInt) then
                            exitwhen true //found last integer, so exit
                        else
                            set foundNegative = false
                        endif
                        set count = count + 1
                    endloop
                    if (foundInt) then
                        set arg = SubString(val, start, count)
                    endif
                //rips out a real
                elseif (typeToRip == StringType.REAL) then
                    set foundInt = false
                    set count = 0
                    set foundNegative = false
                    set foundDecimal = false
                    loop
                        exitwhen count == length
                        set char = SubString(val, count, count+1)
                        if (char == "-" and not foundInt) then
                            set start = count
                            set foundNegative = true
                        elseif (char == "." and not foundDecimal) then
                            if (not foundNegative) then
                                set start = count
                            endif
                            set foundDecimal = true
                        elseif (char == "0" or char == "1" or char == "2" or char == "3" or char == "4" or char == "5" or char == "6" or char == "7" or char == "8" or char == "9") then
                            if (not foundNegative and not foundDecimal and not foundInt) then
                                set start = count
                            endif
                            set foundInt = true
                        elseif (foundInt) then
                            exitwhen true //found last integer, so exit
                        else
                            set foundNegative = false
                            set foundDecimal = false
                        endif
                        set count = count + 1
                    endloop
                    if (foundInt) then
                        set arg = SubString(val, start, count)
                    endif
                else
                    set arg = val
                endif
            endif
            
            return arg
        endmethod
        
        //rips out all strings of a specific type and returns a StringStack containing those strings
        //slow but extremely flexible
        public static method ripType takes string val, integer typeToRip returns StringStack
            local string arg = null
            local string args = null
            local integer length
            local integer count
            local string char
            local integer argLength
            local integer boolCount
            local boolean foundDecimal
            local boolean foundInt
            local integer start
            local boolean foundNegative
            local integer argCount = 0
            
            if (val != null) then
                set length = StringLength(val)
                set count = 0
                
                //rip null, which is easy, lol
                if (typeToRip == StringType.NULL) then
                    set argCount = 1
                    set args = null
                //rip boolean, which tries to piece together straight** chars that could build boolean
                elseif (typeToRip == StringType.BOOLEAN) then
                    set count = 4
                    set arg = null
                    loop
                        loop
                            exitwhen count > length
                            //check for true
                            set arg = SubString(val, count-4, count)
                            if (arg != "true") then
                                set arg = null
                                exitwhen count > length
                                set arg = SubString(val, count-4, count+1)
                                if (arg != "false") then
                                    set arg = null
                                    set count = count + 1
                                    exitwhen count > length
                                endif
                            endif
                            exitwhen arg != null
                        endloop
                        exitwhen arg == null
                        set argCount = argCount + 1
                        if (args == null) then
                            set args = arg
                        else
                            set args = " " + arg
                        endif
                    endloop
                //rip out an ascii value
                elseif (typeToRip == StringType.ASCII) then
                    set count = 3
                    loop
                        loop
                            exitwhen count > length
                            set arg = SubString(val, count-3, count)
                            if (SubString(arg, 0, 1) != "'" or SubString(arg, 2, 3) != "'") then
                                set arg = null
                                exitwhen count+3 > length
                                set arg = SubString(val, count-3, count+3)
                                if (SubString(arg, 0, 1) != "'" or SubString(arg, 5, 6) != "'") then
                                    set arg = null
                                    set count = count + 1
                                    exitwhen count > length
                                endif
                            endif
                            exitwhen arg != null
                        endloop
                        exitwhen arg == null
                        set argCount = argCount + 1
                        if (args == null) then
                            set args = arg
                        else
                            set args = " " + arg
                        endif
                    endloop
                //rips out a plain old integer
                elseif (typeToRip == StringType.INTEGER) then
                    set count = 0
                    loop
                        set foundInt = false
                        set foundNegative = false
                        loop
                            exitwhen count == length
                            set char = SubString(val, count, count+1)
                            if (char == "-" and not foundInt) then
                                set start = count
                                set foundNegative = true
                            elseif (char == "0" or char == "1" or char == "2" or char == "3" or char == "4" or char == "5" or char == "6" or char == "7" or char == "8" or char == "9") then
                                if (not foundNegative and not foundInt) then
                                    set start = count
                                endif
                                set foundInt = true
                            elseif (foundInt) then
                                exitwhen true //found last integer, so exit
                            else
                                set foundNegative = false
                            endif
                            set count = count + 1
                        endloop
                        exitwhen not foundInt
                        set argCount = argCount + 1
                        if (args == null) then
                            set args = SubString(val, start, count)
                        else
                            set args = args + " " + SubString(val, start, count)
                        endif
                    endloop
                //rips out a real
                elseif (typeToRip == StringType.REAL) then
                    set count = 0
                    loop
                        set foundNegative = false
                        set foundDecimal = false
                        set foundInt = false
                        loop
                            exitwhen count == length
                            set char = SubString(val, count, count+1)
                            if (char == "-" and not foundInt) then
                                set start = count
                                set foundNegative = true
                            elseif (char == "." and not foundDecimal) then
                                if (not foundNegative) then
                                    set start = count
                                endif
                                set foundDecimal = true
                            elseif (char == "0" or char == "1" or char == "2" or char == "3" or char == "4" or char == "5" or char == "6" or char == "7" or char == "8" or char == "9") then
                                if (not foundNegative and not foundDecimal and not foundInt) then
                                    set start = count
                                endif
                                set foundInt = true
                            elseif (foundInt) then
                                exitwhen true //found last integer, so exit
                            else
                                set foundNegative = false
                                set foundDecimal = false
                            endif
                            set count = count + 1
                        endloop
                        exitwhen not foundInt
                        set argCount = argCount + 1
                        if (args == null) then
                            set args = SubString(val, start, count)
                        else
                            set args = args + " " + SubString(val, start, count)
                        endif
                    endloop
                else
                    set argCount = 1
                    set args = arg
                endif
            endif
            
            if (argCount == 0) then
                return 0
            elseif (argCount == 1) then
                return StringStack.advCreateSingle(args, typeToRip)
            else
                return StringStack.advCreate(args, " ", typeToRip)
            endif
        endmethod
        
        private static method onInit takes nothing returns nothing
            set typeNames[NULL] = "null"
            set typeNames[BOOLEAN] = "boolean"
            set typeNames[ASCII] = "ascii"
            set typeNames[INTEGER] = "integer"
            set typeNames[REAL] = "real"
            set typeNames[STRING] = "string"
        endmethod
    endstruct
endlibrary


Rip Demonstration
JASS:
struct tester extends array
    private static trigger t = CreateTrigger()
    
    private static method test takes nothing returns boolean
        //ascii would take input like 'hpea'
        //dfsa'h'fea' -> 'h'
        //dah'afsdoiaf'sdfaoi'dsfajfad' -> 'afsd'
        local string arg = StringType.rip(GetEventPlayerChatString(), StringType.ASCII)
        call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, arg)
        return false
    endmethod
    
    private static method onInit takes nothing returns nothing
        call TriggerRegisterPlayerChatEvent(t, Player(0), "", false)
        call TriggerAddCondition(t, Condition(function thistype.test))
    endmethod
endstruct


Parser + typeof + converter demonstration
JASS:
struct tester extends array
    private static trigger t = CreateTrigger()
    
    private static method test takes nothing returns boolean
        //delimiter
        //local StringStack stringStack = StringStack.create(GetEventPlayerChatString(), StringStack.ARG_DELIMITER)
        
        //type+delimiter
        local StringStack stringStack = StringStack.createByType(GetEventPlayerChatString(), StringStack.ARG_DELIMITER)
        
        //rest of code
        local StringStack node = stringStack
        local integer stringType
        
        local boolean b
        local integer a
        local integer i
        local real r
        local string s
        
        local string bs
        local string as
        local string is
        local string rs
        local string ss
        
        local string value
        loop
            exitwhen node == 0
            set value = node.value
            set stringType = node.stringType
            
            if (stringType == StringType.NULL) then
                set s = value
                call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, StringType[stringType] + ": " + s)
            elseif (stringType == StringType.BOOLEAN) then
                set b = StringType.S2B(value)
                set bs = StringType.B2S(b)
                call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, StringType[stringType] + ": " + bs)
            elseif (stringType == StringType.ASCII) then
                set a = StringType.S2A(value)
                set as = StringType.A2S(a)
                call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, StringType[stringType] + ": " + as)
            elseif (stringType == StringType.INTEGER) then
                set i = S2I(value)
                set is = I2S(i)
                call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, StringType[stringType] + ": " + is)
            elseif (stringType == StringType.REAL) then
                set r = S2R(value)
                set rs = R2S(r)
                call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, StringType[stringType] + ": " + rs)
            elseif (stringType == StringType.STRING) then
                call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, StringType[stringType] + ": " + value)
            endif
            
            //set node = node.next
            set node = node.pop()
        endloop
        
        //call stringStack.destroy()
        return false
    endmethod
    
    private static method onInit takes nothing returns nothing
        call TriggerRegisterPlayerChatEvent(t, Player(0), "", false)
        call TriggerAddCondition(t, Condition(function thistype.test))
    endmethod
endstruct


Filter String Demo
JASS:
struct tester extends array
    private static trigger t = CreateTrigger()
    
    private static method test takes nothing returns boolean
        local string filtered = FilterString(GetEventPlayerChatString(), "-", false)
        call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, filtered)
        return false
    endmethod
    
    private static method onInit takes nothing returns nothing
        call TriggerRegisterPlayerChatEvent(t, Player(0), "", false)
        call TriggerAddCondition(t, Condition(function thistype.test))
    endmethod
endstruct
 

Attachments

  • test map.zip
    27.5 KB · Views: 229

tooltiperror

Super Moderator
Reaction score
231
The coding looks fine as far as I can see, but shouldn't you link to Ascii in your post (i.e. not in the documentation/JASS tags)?
 

Nestharus

o-o
Reaction score
84
The coding looks fine as far as I can see, but shouldn't you link to Ascii in your post (i.e. not in the documentation/JASS tags)?

I link in documentation so that if someone has a map that just holds a collection of systems (which I sometimes do), they can easily access required systems in case they lose them or something ; P.
 

Nestharus

o-o
Reaction score
84
posting because I added StringStack.createByType!!! Because I did some measure of smart parsing in it, it was absolute hell to make : D.

1.1.0.0 changes (StringStack.createByType at bottom)
Made rip faster and fixed possible bugs, also made it so that all things have to be consecutive.

Added ripType, which rips a stack of values of a type, like all integers in a string.

Added toString, which converts a stack into a string with a delimiter.

Made typeof faster.

Added StringStack.createByType, which allows you to split a string up by delimiter and type.. very very very useful!! Made it have some decently smart parsing for when it detects a new type as well to make it a bit faster.

with delimiter of " "
+1.1+1-1'hpea'hellotrue hi

outputs

+ 1.1 + 1 -1 'hpea' hello true hi
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top