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
changelog
Rip Demonstration
Parser + typeof + converter demonstration
Filter String Demo
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
1.1.0.1added 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.0Fixed a small bug in createByType
1.0.3.5Made 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.4made parser loop faster
1.0.3.3Made parser handle delimiter as first characters properly
1.0.3.2Made StringStack parser a bit better (now correctly handles masses of delimiter characters that are placed next to each other)
1.0.3.1Made typof recognize values with negative flags as integers/reals
1.0.3.0Optimized create a bit
1.0.2.1added 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.0added DELIMITER global at top to make setting ARG_DELIMITER easier
1.0.1.0added StringType.compare
1.0.0.1Added FilterString
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) != "039;" or SubString(val, length-1, length) != "039;") 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 == "039;") then //either ascii or string
if (start+3 <= length) then
if (SubString(val, start+2, start+3) == "039;") then
set subLength = start + 3
set curType = StringType.ASCII
exitwhen true
elseif (start+6 <= length and SubString(val, start+5, start+6) == "039;") 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 == "039;" and subLength+2 <= length) then
if (SubString(val, subLength+1, subLength+2) == "039;") 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) == "039;") 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 = "039;"
loop
exitwhen val == 0
set ascii = ascii + Ascii2Char(val - val/128*128)
set val = val / 128
endloop
return ascii + "039;"
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) != "039;" or SubString(arg, 2, 3) != "039;") then
set arg = null
exitwhen count+3 > length
set arg = SubString(val, count-3, count+3)
if (SubString(arg, 0, 1) != "039;" or SubString(arg, 5, 6) != "039;") 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) != "039;" or SubString(arg, 2, 3) != "039;") then
set arg = null
exitwhen count+3 > length
set arg = SubString(val, count-3, count+3)
if (SubString(arg, 0, 1) != "039;" or SubString(arg, 5, 6) != "039;") 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