Talk:LlGetListEntryType

From Second Life Wiki
Jump to navigation Jump to search

List entries that are strings, but look like other types

(Maybe there's a shorter title for this topic?)

Most of us who have ever had to "unserialize" know that this function returns a type of TYPE_STRING when we have ["<123, 45.4, 0>"]. I have a list coming to me that is like unto ["blah", "133", "1.04"]. So far I can find out what is an integer by using this magic:

    tempStr = llList2String(raw, index);
    if ((string) ((integer) tempStr) == tempStr) { // Test for integer,
        ....
    }

An else will handle the string nicely, as anything that is not an integer/float/etc. is therefore a string... But I can't figure out how to detect a float. Any ideas?
Cron Stardust 23:21, 7 March 2007 (PST)

Using your technique to determine the type by examining the data is going to be flawed and slow. It is best to include type data in your output. Try out TightListTypeParse and TightListTypeDump on my userpage. If you are interested I'll post the Tightlist ESL header file (the advantage of that being there are extra features to the functions that aren't included by default). Strife Onizuka 05:08, 8 March 2007 (PST)
If I was programmatically controlling both ends, that would work beautifully. But I have users typing a long string that is then parsed into a list, then each element is turned into it's own datatype. I know it is a flawed system as (float) "45.4" != 45.4 but the rounding errors are something that I don't think will cause too many problems in my application.
What I figured out in answer to my own question was:
integer isFloat(string data) {
    string elem;
    integer hasDeci = FALSE;

    integer len = llStringLength(data);
    for (index = 0; index < len; ++index) {
        elem = llGetSubString(data, index, index);
        if (elem != "0" &&
            elem != "1" &&
            elem != "2" &&
            elem != "3" &&
            elem != "4" &&
            elem != "5" &&
            elem != "6" &&
            elem != "7" &&
            elem != "8" &&
            elem != "9" &&
            elem != ".") {
            return FALSE;
        }
        else if (elem == "." && hasDeci == FALSE) { // Fix for bug mentioned later.
            hasDeci = TRUE;
        }
        else if (elem == "." && hasDeci == TRUE) {
            return FALSE;
        }
    }
    
    return TRUE;
}
I know, it's going to be slow. If there is a way to optimize, or another, better, solution...
Cron Stardust 21:09, 8 March 2007 (PST)
User input can be a problem that way. Out of curiosity, what are you scripting that you don't already know the datatype of the input? Strife Onizuka 04:24, 9 March 2007 (PST)
A pseudo-language for rezzing objects. I hope to release the language spec to others, but only after I've sold a few of my interpreters. There are two ways to work with the input and I was looking to use this this technique to solve the problem of finding out if the user/programmer typed in the correct datatype. The other way is to assume that I know what the datatype is, and just run with it. But that can be fun because LSL converts (integer) "abc" into 0. (As it should.) What I would like to have it do is error out (llRaiseError anyone?) and tell the user/programmer that "HEY! you have the wrong datatype there!!!
Also, note the values returned in this block of code:
        llOwnerSay((string) ((integer) "abc123")); // = 0
        llOwnerSay((string) ((integer) "123abc")); // = 123
        llOwnerSay((string) ((integer) "abc"));    // = 0
        llOwnerSay((string) ((integer) "123"));    // = 123
At first I didn't expect that second return, but it's ok. it would fail both my integer test, and my isFloat. But note that isFlaot will return TRUE on a string like "......." which means it needs to make sure that there is A MAX of ONE period, and AT LEAST ONE number.
Cron Stardust 18:46, 11 March 2007 (PDT)
I see what you mean now. Hmmm that is a problem, especially when you consider the hex-float syntax. Regex would be the solution to your problem. Implementing Regex in LSL would suck (and be slow). I would be inclined to write it so that it allows the user to have trailing junk and have it try to catch corruption by checking for defaults. It's not a perfect solution but it works well enough.
integer isRot(string a)
{
    if((rotation)a)
        return 1;
    list b = llParseString2List(a, [",","<",">"],[" "]);
    if(llList2String(a,0) == "<")
    {
		if((float)llList2String(b,1));
		else if(llList2String(b,2) == ",")
			if((float)llList2String(b,3));
			else if(llList2String(b,4) == ",")
				if((float)llList2String(b,5));
				else if(llList2String(b,6) == ",")
					return (float)llList2String(b,7) == 1.0;
	}
	return 0;
}

integer isVec(string a)
{
    if((rotation)a)//rotations are valid vectors
        return 0;//this can be exploited to make interfaces that support both euler and quaternion angle inputs.
    if((vector)a)
        return 1;
    list b = llParseString2List(a, [",","<",">"],[" "]);
    if(llList2String(a,0) == "<")
    {
		if((float)llList2String(b,1));
		else if(llList2String(b,2) == ",")
			if((float)llList2String(b,3));
			else if(llList2String(b,4) == ",")
				return (float)llList2String(b,5) != 0.0;
	}
	return 0;
}
Strife Onizuka 06:20, 12 March 2007 (PDT)
Isn't your llParseString2List backwards? It looks like you are dropping the [",","<",">"] symbols and keeping the spaces, then testing for the symbols you dropped... But otherwise, really cool functions! I also updated my isFloat function to respond correctly to a string of "...." or "12.3.4" (IE: return FALSE in those cases.)
Also, would your functions return TRUE if they were sent <0,0,0,1> and <0,0,0> respectively?
Cron Stardust 16:36, 12 March 2007 (PDT)