Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Yet Another Multidimensional Array Script

Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
06-08-2005 23:35
Hey all, I ran into another problem where multidimensional arrays would have *really* helped, so I decided to spend another day on finding out a way to stuff the data into LSL's list structure.

So here goes:
CODE

// Generates a random string of length len
// from the characters passed to it.
string randomSeperatorFrom(string chars, integer len) {
integer numChars = llStringLength(chars);
integer firstIndex = (integer) llFrand(numChars);
string first = llGetSubString(chars, firstIndex, firstIndex);
if (len == 1)
return first;
chars = llDeleteSubString(chars, firstIndex, firstIndex);
--numChars;
// Generate the last character.
integer lastIndex = (integer) llFrand(numChars);
string last = llGetSubString(chars, lastIndex, lastIndex);
if (len == 2)
return first + last;
chars = llDeleteSubString(chars, lastIndex, lastIndex);
--numChars;
// Generate the string between the first and last chars.
string middle;
integer i;
for (i = 2; i < len; ++i) {
integer randIndex = (integer) llFrand(numChars);
middle += llGetSubString(chars, randIndex, randIndex);
}
return first + middle + last;
}

string SEPERATOR_CHARS = "`~!@#$%^&*()-_+[]{}\|'\";/?.>,<";
integer SEPERATOR_LEN = 3;
string dumpList2String(list src) {
// Generate a seperator not present in any of the
// elements in the list.
string chars = (string) src; // Squashes all elements together.
string seperator;
do {
seperator = randomSeperator(SEPERATOR_CHARS, SEPERATOR_LEN);
} while (llSubStringIndex(chars, seperator) != -1);
return seperator + llDumpList2String(src, seperator);
}

list parseStringKeepNulls(string src) {
// The seperator should be the first SEPERATOR_LEN
// characters in the string.
return llParseStringKeepNulls(llDeleteSubString(src, 0, SEPERATOR_LEN - 1),
[llGetSubString(src, 0, SEPERATOR_LEN - 1)], []);
}

string NULL = "";
list listReplaceList(list dest, list src, integer start, integer ensureLocation) {
if (ensureLocation && llGetListEntryType(dest, start - 1) == TYPE_INVALID) {
// Fill with nulls until we get to the starting position.
integer len = llGetListLength(dest);
for (len = llGetListLength(dest); len < start; ++len) {
dest += NULL;
}
}
return llListReplaceList(dest, src, start, start + llGetListLength(src) - 1);
}

list getElementAt(list array, list index){
if (index == [])
return array;
integer numIndicies = llGetListLength(index);
list src = array;
integer i;
for (i = 0; i < numIndicies - 1; ++i) {
integer listIndex = llList2Integer(index, i);
string element = llList2String(src, listIndex);
if (llGetSubString(element, 0, 0) == "l")
element = llDeleteSubString(element, 0, 0);
src = parseStringKeepNulls(element);
}
string element = llList2String(src, llList2Integer(index, -1));
if (llGetSubString(element, 0, 0) == "l") {
// Caller is retreiving a dimension.
return parseStringKeepNulls(llDeleteSubString(element, 0, 0));
} else {
return [element];
}
}

// To set an element, we need to extract
// each list starting from where exactly the
// new data will be. In a set of russian dolls, this
// would be equivelant to grabbing the littlest one
// first. then gradually adding back on the layers over it.
// I think its easiest to do this recursively.
list setElementAt(list array, list data, list index) {
string element;
if (llGetListLength(data) > 1) {
// Data is a new dimension:
element = "l" + dumpList2String(data);
} else {
// Data is a single element
element = llList2String(data, 0);
}
if (llGetListLength(index) > 1) {
// index is in the form [a,b,c,d]
// here, we grab the list that d is in.
list containerIndex = llDeleteSubList(index, -1, -1);
list dest = getElementAt(array, containerIndex);
integer listIndex = llList2Integer(index, -1); // Grab d
dest = listReplaceList(dest, [element], listIndex, TRUE); // replace the element in d's list.
// Make sure the recursion treats the container like a list, not an element.
if (llGetListLength(dest) == 1)
dest += "";
return setElementAt(array, dest, containerIndex);
} else {
return listReplaceList(array, [element], llList2Integer(index, 0), TRUE);
}
}


Features:
1. Dynamic arrays: No need to specify dimension length!
2. "Ragged" arrays: Its truly lists in lists - any size list can be put into any other list.

Testing welcome :D

... and before you say "didn't you do this already?" -- eh, nevermind :)
==Chris
Also see the wiki library post for more details.
_____________________
October 3rd is the Day Against DRM (Digital Restrictions Management), learn more at http://www.defectivebydesign.org/what_is_drm
Nada Epoch
The Librarian
Join date: 4 Nov 2002
Posts: 1,423
Discussion Thread
06-18-2005 09:53
/54/0f/50710/1.html
_____________________
i've got nothing. ;)