[Edit: Adjusted to compile in both LSL, LSLEditor and MONO, also added Exponent test to Int, Float and Numeric]
A group of little utility functions that others may find useful.
I know it could be more readable but I was after performance over legibility.
Each function may be used alone, but are grouped here for ease of posting.
Any one care to comment if there is a more efficient method of achieving this, or if the exceptions are a showstopper? The only exceptions I have found in my testing are 12. And .12 are not seen as numeric, however 12.0 and 0.12 are correctly identified as numeric and as float, I see this as mathematically correct even though LSL recognises the format without 0.
CODE
integer isInt(string val)
//is the string val a valid integer?
{
integer exp;//if an exponent is present we need to record its position
//remove white space, convert any Alpha charecters to lowercase and see if the first charecter is "-"
//if it is then remove it
if(!llSubStringIndex(val = llStringTrim(llToLower(val),STRING_TRIM),"-"))val = llGetSubString(val,1,-1);
//does the value have an exponent?
if(~(exp = llSubStringIndex(val,"e")))
//if it has and the exponent is negative, in all likelyhood, this value will be a float so abort
{if("-" == llGetSubString(val,exp + 1, exp + 1))return FALSE;
//otherwise remove the exponent from the string
else val = llGetSubString(val,0,exp - 1);}
//all special charecters should now be gone so remove the valid numerals, if anything is left then this is not a valid integer.
return !llStringLength(llDumpList2String(llParseString2List(llDumpList2String(llParseString2List(val,["0","1","2","3","4"],[]),""),["5","6","7","8","9"],[]),""));
}
integer isFloat(string val)
//is the string val a valid Float?
{
integer point; integer exp;//if an exponent or a point are present we need to record the positions
//remove white space, convert any Alpha charecters to lowercase and see if the value has an exponent
if(~(exp = llSubStringIndex(val = llStringTrim(llToLower(val),STRING_TRIM),"e")))
//determine if the exponent is negative then remove the exponent from the string
//both variables are used out of context to avoid the overhead of decclaring a 3rd variable.
{point = llSubStringIndex(llGetSubString(val,exp + 1,exp + 1),"-");val = llGetSubString(val,0,exp - 1);exp = point;}
//look for the decimal point and if present remove it from the string
if(~(point = llSubStringIndex(val,".")))val = llGetSubString(val,0, point - 1) + llGetSubString(val, point + 1, -1);
//if there was no decimal point and the exponent, if any, was not negative this is not a float so abort
else if(!(~exp))return FALSE;
//finaly, if this is a negative number, remove the "-"
if(!llSubStringIndex(val,"-"))val = llGetSubString(val,1,-1);
//all special charecters should now be gone so remove the valid numerals, if anything is left then this is not a valid Float.
return !llStringLength(llDumpList2String(llParseString2List(llDumpList2String(llParseString2List(val,["0","1","2","3","4"],[]),""),["5","6","7","8","9"],[]),""));
}
integer isHex(string val)
{
//is the string val a valid Hex Number?
integer point;
//remove white space, convert any Alpha charecters to lowercase and see if the first charecter is "-"
//if it is then remove it
if(!llSubStringIndex(llStringTrim(llToLower(val),STRING_TRIM),"-"))val = llGetSubString(val,1,-1);
//LSL recognises "0x" as the Hex prefix, if it is not present this is not hex so abort, otherwise remove it.
if(~llSubStringIndex(val,"0x"))val = llGetSubString(val,2,-1);else return FALSE;
//look for the decimal point and if present remove it from the string
if(~(point = llSubStringIndex(val,".")))val = llGetSubString(val,0, point - 1) + llGetSubString(val, point + 1, -1);
//LSL (float) typecast supports C99 hex floats so look for the "p" and remove it
if(~(point = llSubStringIndex(val,"p")))val = llGetSubString(val,0,point - 1);
//all special charecters should now be gone so remove the valid numerals, if anything is left then this is not a valid Hex Number.
return !llStringLength(llDumpList2String(llParseString2List(llDumpList2String(llParseString2List(val,["0","1","2","3","4","5","6","7"],[]),""),["8","9","a","b","c","d","e","f"],[]),""));
}
integer isNumeric(string val)
{
//is val in a format that LSL will corectly interprate as a number?
integer point; list mask = ["8","9"];//our mask has 2 forms Decimal and Hex, we will default it to decimal
//remove white space, convert any Alpha charecters to lowercase look for the decimal point and if present remove it from the string
if(~(point = llSubStringIndex(val = llStringTrim(llToLower(val),STRING_TRIM),".")))val = llGetSubString(val,0,point - 1)+llGetSubString(val,point + 1, -1);
//look for an exponant, as we dont care if it is possitive or negative in this case just remove it
if(~(point = llSubStringIndex(val,"e")))val = llGetSubString(val,0,point - 1);
//and do the same thing for a possible Hex Flat exponent of "p"
if(~(point = llSubStringIndex(val,"p")))val = llGetSubString(val,0,point - 1);
//if this is a negative number, remove the "-"
if(!llSubStringIndex(val,"-"))val = llGetSubString(val,1,-1);
//LSL recognises "0x" as the Hex prefix, if it is present remove it and use the Hex mask for the final test.
if(!llSubStringIndex(val,"0x")){val = llGetSubString(val,2,-1); mask = ["8","9","a","b","c","d","e","f"];}
//all special charecters should now be gone so remove the valid numerals, if anything is left then this is not a valid Number.
return !llStringLength(llDumpList2String(llParseString2List(llDumpList2String(llParseString2List(val,["0","1","2","3","4","5","6","7"],[]),""),mask,[]),""));
}
default
{
state_entry()
{
llListen(0,"","","");
}
listen(integer channel, string name, key id, string message)
{
llOwnerSay("Numeric "+(string)isNumeric(message));
llOwnerSay("Integer "+(string)isInt(message));
llOwnerSay("Hex "+(string)isHex(message));
llOwnerSay("Float "+(string)isFloat(message));
llOwnerSay("result int = "+(string)((integer)message)+" float = "+(string)((float)message));
llOwnerSay((string)llGetFreeMemory());
}
}
The test code should be self-explanatory.
Thanks in advance for any feedback.
Voted.