llList2TypedString and llTypedString2List
tracked
Chaser Zaks
LSL has the issue where some lists need to be typed,
cough
llSetLinkPrimitiveParams
cough
.It's important to be able to store types when storing a string, say to either a remote server, or
llLinkSetData
, or even just transmitting it from one object to another.The design philosophy behind this idea is three points:
- Be compact
- Be easy to implement (for residents who need to make code to do this)
- Solve the issue
The functions are:
*
string llList2TypedString(list data);
*
list llTypedString2List(string data);
The syntax is as follows:
*
i
precedes a integer, if no integer is found, it represents 0. (Hexidecimal is supported because of std::stoi
)*
r
("r" as in Real!) precedes a float, if no float is found, it represents 0. Preceding zero are optional for values between 0 and 1.*
v
precedes a vector, if no vector is found, it represents zero. If any value is zero, it may be omitted. I.E. v,1
is valid for <0,1,0>
, as well as v,,1
being for <0,0,1>
.*
q
precedes a quaternion, it shares the same behavior as a vector (Quite literally the same code!)*
k
precedes a key. It reads exactly 36 BYTES, unless the first byte is "-"*
s
precedes a string. It is defined by specifying a integer length, followed by a colon, then the string. If no string or simply a semicolon, it represents a empty string.* Lists are unsupported, lists may not contain lists.
* Any of the above may be combined in series to form a list.
I've provided a lscript implementation at the top of this post.
Log In
Bleuhazenfurfle Resident
This is an awesome idea, but, there be weeds… There's no suitable standard, so I think you'd need to version it along the lines of Python's pickle. This would be version 0; simple, obvious, and rather verbose, but also easy to handle in external servers.
Each version would be because someone found a significantly smaller encoding than the ones before it, with a constant holding the smallest version so far (not expecting more than two or three). For LSL <-> LSL, you can use the latest version by just prepending the version number onto the produced string (a single digit should be enough — a lot of versioning can be done simply by adopting new type characters, like that K), and even older scripts will still be able to read it by just pulling that number back off again first, and feeding it into the appropriate argument — I would handle attaching the version number manually when it's wanted, because otherwise you'll have issues joining or splitting the output strings (and it's not always even necessary). I would however, also additionally have a string constant with the joiner characters used in each version (most likely it'll just be a string of the same character N times, but there may be a reason to change it some day).
The one I did about half a decade or so ago, encoded numbers into the highest base I could find as to fit as much into a single notecard line as possible — but that made it ssslllooooooooowww, which is where a built-in would have been awesome… (Also employed some tricks to fold negatives, floats as regular integers, and valid keys as really big regular integers) That would be a good version 1.
A function that reads N terms is also extremely useful, and allows you to quite readily encode lists within a longer stream — I had mine return what was left of the input string as the first item in the returned list (also, if it encountered a malformed value at any point).
Spidey Linden
tracked
Issue tracked. We have no estimate when it may be implemented. Please see future updates here.
Chaser Zaks
I've updated the code so that "K" is for arbitrary strings as keys(EG:
(key)"Invalid key!"
), and fixed an issue with vectors/quaternions parsing invalid entries incorrectly, also use LLUUID::validate
, LLUUID::null
and UUID_STR_LENGTH
instead of magic numbers.Also added whitespaces to ignored token types.
Chaser Zaks
I completely forgotten to include an example and it was just pointed out to me.
default
{
state_entry()
{
string test = llList2TypedString([
1, 2, 3,
(key)NULL_KEY,
(key)TEXTURE_DEFAULT,
<-1234, 0.1234, 123.456>,
1234.5678,
0.12,
"This is a string █ |",
<1234, 0.1234, 123.456, -1234>,
<0,0,0>,
"",
(key)"Invalid key!"
]);
print(test);
print(llTypedString2List(test));
}
}
returns
i1i2i3k89556747-24cb-43ed-920b-47caed15465fv-1234,.1234,123.456001r1234.567749r.12s20:This is a string █ |q1234,.1234,123.456001,-1234vsK12:Invalid key!
Notice how it preserves types in the string. You can then put it through
llTypedString2List
and then be able to use llGetListType on it and see that the types are preserved.Chaser Zaks
I've updated the code to further shrink the size of the typed list.
Keys now validate, and
k-
is just k
now.I realize that some people, for whatever reason, may want to store arbitrary strings as keys. If this is a requested addition, a change can be done to include
K
as well, which means "arbitrary string as key", which is treated exactly like a string, but is stored in mKey
instead. This would be a very simple addition.Ash Qin
I had implemented something similar in LSL due to a need for it myself. Although instead of letters, used the integers returned by llGetListEntryType to determine types. Not advocating that be used, but would love to see this type of functionality added.
Bavid Dailey
not sure why this
needs
to an LSL function, although it would be nice. I will copy this script into my general inlcude library (firestorm feature) Perhaps what we really should be asking for is a standard way to have an include feature in all the viewers
Chaser Zaks
Bavid Dailey It isn't a LSL function per say, it's the C++ implementation that makes the functions work in LSL.
Bavid Dailey
Chaser ZaksOops sorry, i realised that after I posted the comment; and I
thought
I had deleted the comemnt. Clearly I hadn't - mea culpa