User:ANSI Soderstrom/Simple LSL Array (Associative)
Jump to navigation
Jump to search
Leave a comment
Simple LSL Array (Associative)
<lsl> // Simple LSL Array (associative) for your Scripts (useful and very fast) // (C) 02/2010 ANSI Soderstrom
list SOMELIST;
string GET(list ARRAY,list KEY) {
if(!llGetListLength(KEY)>1) {
// dont allow lists in lists (yet)
return "-1";
}
integer position;
do {
// Have a look to the nearest next possible match (can be a KEY or VALUE)
position = llListFindList(ARRAY, KEY);
// position%2 = we point ever to a KEY, not to a VALUE
// ~position = only process the condition if the list contains a KEY with the right given spelling (and Type)
// position = position should be not zero, we dont want to delete the right KEY, we will return him
if(position%2 && ~position && position) {
// no match in this case, delete this pair and process the next pair
ARRAY = llDeleteSubList(ARRAY,0,position);
}
// loop if
// ~position = a further possible match for a KEY or VALUE
// position%2 = the nearest next possible match is a VALUE. Back to work
} while (~position && position%2);
if(~position) {
// we have a HIT !!! (hurray) return the VALUE
return llList2String(ARRAY,position+1);
} else {
// we are in fact at the end of the list and have no matches
return "0";
}
}
list PUT(list ARRAY,list KEY, list VALUE) {
if(llGetListLength(KEY)>1 || llGetListLength(VALUE)>1) {
// dont allow lists in lists (yet)
// Maybe its smarter at this point to return the whole untouched Array because the script is not broken
// if we call this function dynamically
// return ARRAY;
return [-1];
}
// just curious and impatient at this point... (i never have enough time and need quick solutions because life is too short)
// (this means : i hate to execute double-code and we can find the same line some lines below)
integer position = llListFindList(ARRAY, KEY);
// maybe we need a helplist. here is a good place to create this list.
list helparray = [];
do {
// !~position = We have in the whole remaining list no KEY with this type, so we add simply the KEY and VALUE and go out.
if(!~position) {
ARRAY += KEY;
ARRAY += VALUE;
return helparray + ARRAY;
}
// position%2 = we point ever to a KEY, not to a VALUE
// ~position = only process the condition if the list contains KEYs with the right given spelling (and Type)
// position = position should be not zero (Oh, its a VALUE), we dont want to delete the right KEY, we will overwrite him
if(position%2 && ~position && position) {
// save the previous list in a second list, so we can work (delete) on parts in the original list without data-loss
helparray += llList2List(ARRAY,0,position);
// delete the unwanted stuff
ARRAY = llDeleteSubList(ARRAY,0,position);
// search the next match in the (shorter) original list
position = llListFindList(ARRAY, KEY);
}
// the next possible match is in fact a VALUE if position%2 != 0. So back to work
} while (position%2);
// We know that the list have definitely the KEY we searching for (because '!~position' is not triggered yet)
// seems that we have a match (because position==0). We can overwrite the VALUE for the given KEY at this point
ARRAY = llListReplaceList(ARRAY, VALUE, position + 1, position + 1);
// re-build the list and back to normal operations
return helparray + ARRAY;
}
list ERASE(list ARRAY,list KEY) {
if(!llGetListLength(KEY)>1) {
// dont allow lists in lists (yet)
// Maybe its smarter at this point to return the whole untouched Array because the script is not broken
// if we call this function dynamically
// return ARRAY;
return [-1];
}
// just curious and impatient at this point... (i never have enough time and need quick solutions because life is too short)
// (this means : i hate to execute double-code and we can find the same line some lines below)
integer position = llListFindList(ARRAY, KEY);
// maybe we need a helplist. here is a good place to create this list.
list helparray = [];
do {
// !~position = no match in the whole remaining list. Erase nothing and go out
if(!~position) {
return helparray + ARRAY;
}
// position%2 = we point ever to a KEY, not to a VALUE
// ~position = only process the condition if the list contains KEYs with the right given spelling (and Type)
// position = Oh, its a VALUE.
if(position%2 && ~position && position) {
// save the previous list in a second list, so we can work (delete) on parts in the original list without data-loss
helparray += llList2List(ARRAY,0,position);
// delete the unwanted stuff
ARRAY = llDeleteSubList(ARRAY,0,position);
// search the next match in the (shorter) original list
position = llListFindList(ARRAY, KEY);
}
// the next possible match is in fact a VALUE if position%2 != 0. Back to work
} while (position%2);
// seems that we have a match. We can delete this KEY/VALUE pair
ARRAY = llDeleteSubList(ARRAY,position, position + 1);
// re-build the list and back to normal operations
return helparray + ARRAY;
} </lsl>
What do those lines do?
<lsl> default {
state_entry() {
// --------------------------------------------------------------------------------
// Add new KEY/VALUE to the "Array" while the KEY is non existent
SOMELIST = PUT(SOMELIST,["KEY"],["VALUE"]);
SOMELIST = PUT(SOMELIST,[AGENT],[<1,1,1>]);
SOMELIST = PUT(SOMELIST,["TEST"],["VALUE"]);
SOMELIST = PUT(SOMELIST,["VALUE"],["TEST"]);
llSay(0,GET(SOMELIST,["KEY"])); // Output : VALUE
llSay(0,GET(SOMELIST,[AGENT])); // Output : <1.000000, 1.000000, 1.000000>
llSay(0,GET(SOMELIST,["TEST"])); // Output : VALUE
llSay(0,GET(SOMELIST,["VALUE"])); // Output : TEST
// --------------------------------------------------------------------------------
// Overwrite the VALUE from the given KEY if KEY is existent
SOMELIST = PUT(SOMELIST,["KEY"],["9adba1b4-a733-4a44-8275-f4a666784d8c"]);
SOMELIST = PUT(SOMELIST,[AGENT],["unknown"]);
SOMELIST = PUT(SOMELIST,["TEST"],["TEST"]);
SOMELIST = PUT(SOMELIST,["VALUE"],["VALUE"]);
llSay(0,GET(SOMELIST,["KEY"])); // Output : 9adba1b4-a733-4a44-8275-f4a666784d8c
llSay(0,GET(SOMELIST,[AGENT])); // Output : unknown
llSay(0,GET(SOMELIST,["TEST"])); // Output : TEST
llSay(0,GET(SOMELIST,["VALUE"])); // Output : VALUE
// --------------------------------------------------------------------------------
// case sensitive KEY´s
SOMELIST = PUT(SOMELIST,["AGENT"],[NULL_KEY]);
SOMELIST = PUT(SOMELIST,[AGENT],[ZERO_ROTATION]);
llSay(0,GET(SOMELIST,["agent"])); // Output : 0
llSay(0,GET(SOMELIST,["AGENT"])); // Output : 00000000-0000-0000-0000-000000000000
llSay(0,GET(SOMELIST,[AGENT])); // Output : <0.000000, 0.000000, 0.000000, 1.000000>
// --------------------------------------------------------------------------------
// Let us play...
SOMELIST = PUT(SOMELIST,[AGENT],llGetObjectDetails(GET(SOMELIST,["KEY"]),([OBJECT_NAME])));
llSay(0,GET(SOMELIST,["KEY"])); // Output : 9adba1b4-a733-4a44-8275-f4a666784d8c
llSay(0,GET(SOMELIST,[AGENT])); // Output : ANSI Soderstrom
// --------------------------------------------------------------------------------
// ANSI Soderstrom is not a KEY, only a VALUE
if(!(integer)GET(SOMELIST,["ANSI Soderstrom"])) {
llSay(0,"Not in List");
} else {
llSay(0,"Found");
}
// Output : Not in List
// --------------------------------------------------------------------------------
llSay(0,llList2CSV(SOMELIST));
/*
Output : KEY, 9adba1b4-a733-4a44-8275-f4a666784d8c,
1, ANSI Soderstrom,
TEST, TEST,
VALUE, VALUE,
AGENT, 00000000-0000-0000-0000-000000000000
*/
// --------------------------------------------------------------------------------
// Extended behavior
list WHITELIST;
list BLACKLIST;
WHITELIST = [ "1234","ANSI Soderstrom",
"4321","Other Name"
];
BLACKLIST = [ "9876","Invisible Linden",
"6789","Visible Linden"
];
// Does NOTHING (no Target List)
PUT(WHITELIST,["1234"],["Any Value"]);
// Dont touch the Blacklist...
// Overwrite Whitelist with Blacklist AND CHANGE the Value of the given Name in the Whitelist
// (because KEY is in Blacklist)
WHITELIST = PUT(BLACKLIST,["9876"],["Changed Name"]);
llOwnerSay(llList2CSV(WHITELIST)); // Whitelist : 9876, Changed Name, 6789, Visible Linden
// Dont touch the Blacklist...
// Overwrite Whitelist with Blacklist AND ADD the given KEY/VALUE to Whitelist
// (because KEY is not in Blacklist)
WHITELIST = PUT(BLACKLIST,["1234"],["Any Value"]);
llOwnerSay(llList2CSV(WHITELIST)); // Whitelist : 9876, Invisible Linden, 6789, Visible Linden, 1234, Any Value
// --------------------------------------------------------------------------------
// Simple eval();
list EVAL = [ "Key 1","Test 1",
"Key 2","Test 2",
"Key 3","Test 3"
];
integer i = llGetListLength(EVAL)/2;
for(;i;--i) {
llSay(0,GET(EVAL,["Key " + (string)i]));
}
// Output:
// Test 3
// Test 2
// Test 1
// --------------------------------------------------------------------------------
// more complex... (Beware of Traps...)
list LIST;
list TEST;
string test;
LIST = PUT(LIST,["1234"],["First Value"]);
LIST = PUT(LIST,[1234],["Second Value"]);
test = llList2CSV(LIST);
llSay(0,test); // Output : 1234, First Value, 1234, Second Value
llSay(0,GET(LIST,["1234"])); // Output : First Value
llSay(0,GET(LIST,[1234])); // Output : Second Value
TEST = llCSV2List(test);
llSay(0,llList2CSV(TEST)); // Output : 1234, First Value, 1234, Second Value
// ARRAY BROKEN AFTER llList2CSV(); !!!
llSay(0,GET(TEST,["1234"])); // Output : First Value
llSay(0,GET(TEST,[1234])); // Output : 0
// --------------------------------------------------------------------------------
// AGENT is a static integer with the value 1
SOMELIST = PUT(SOMELIST,[AGENT],["AGENT"]);
llSay(0,GET(SOMELIST,[1])); // Output : AGENT
llSay(0,GET(SOMELIST,[AGENT])); // Output : AGENT
// --------------------------------------------------------------------------------
// Remember... "AGENT" and AGENT are different, and "AGENT" is a VALUE, not a KEY !!!
if(!(integer)GET(SOMELIST,["AGENT"])) {
llSay(0,"Not in List");
} else {
llSay(0,"Found");
}
// Output : Not in List
// --------------------------------------------------------------------------------
llSay(0,llList2CSV(SOMELIST));
// Output : KEY, 9adba1b4-a733-4a44-8275-f4a666784d8c,
// 1, AGENT,
// TEST, TEST,
// VALUE, VALUE,
// AGENT, 00000000-0000-0000-0000-000000000000
SOMELIST = ERASE(SOMELIST,["KEY"]);
llSay(0,llList2CSV(SOMELIST));
// Output : 1, AGENT,
// TEST, TEST,
// VALUE, VALUE,
// AGENT, 00000000-0000-0000-0000-000000000000
SOMELIST = ERASE(SOMELIST,[AGENT]);
llSay(0,llList2CSV(SOMELIST));
// Output : TEST, TEST,
// VALUE, VALUE,
// AGENT, 00000000-0000-0000-0000-000000000000
SOMELIST = ERASE(SOMELIST,["AGENT"]);
llSay(0,llList2CSV(SOMELIST));
// Output : TEST, TEST,
// VALUE, VALUE,
SOMELIST = ERASE(SOMELIST,["VALUE"]);
llSay(0,llList2CSV(SOMELIST));
// Output : TEST, TEST,
SOMELIST = ERASE(SOMELIST,["TEST"]);
llSay(0,llList2CSV(SOMELIST));
// Output :
// --------------------------------------------------------------------------------
/*
Now you can manage your Settings simple...
list SETTINGS;
SETTINGS = PUT(SETTINGS,["owner"],[llGetOwner()]);
SETTINGS = PUT(SETTINGS,["POS"],[llGetPos()]);
list API;
API = PUT(API,["I_HAVE_THE_SETTINGS"],[-34234242]);
llMessageLinked(LINK_SET,(integer)GET(API,["I_HAVE_THE_SETTINGS"]),llList2CSV(SETTINGS),llGetOwner());
// --------------------------------------------------------------------------------
list SETTINGS;
list API;
API = PUT(API,["I_HAVE_THE_SETTINGS"],[-34234242]);
link_message(integer sender_num, integer num, string str, key id) {
// receive a valid message for this state AND try a further Copy Protection
if(id==llGetCreator() && num==(integer)GET(API,["I_HAVE_THE_SETTINGS"]) {
SETTINGS = llCSV2List(str);
} // if
} // link_message
*/
}
}
</lsl>