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>