List2CSV

From Second Life Wiki
Revision as of 19:16, 12 November 2008 by Kunnis Basiat (talk | contribs)
Jump to navigation Jump to search

List2CSV and CSV2List

Includes escaping all characters, including comma and spaces, so the list that comes out should be just like the list that's sent in.

<lsl> //Thanks to: // http://lslwiki.net/lslwiki/wakka.php?wakka=llCSV2List // https://wiki.secondlife.com/wiki/Library_Combined_Library

string strReplace(string str, string search, string replace) {

   return llDumpList2String(llParseStringKeepNulls((str = "") + str, [search], []), replace);

}

string escapeString(string s) {

   //I'm using forward slashes because backslashes are special chars in LSL
   //    so reading this would be a pain.
   //escape / to /b
   //escape , to /c
   //escape < to /l
   //escape > to /r
   //escape space to /s
   string final = s;
   //backslash must be first when escaping
   final = strReplace(final, "/", "/b");
   
   final = strReplace(final, ",", "/c");
   final = strReplace(final, "<", "/l");
   final = strReplace(final, ">", "/r");
   final = strReplace(final, " ", "/s");
   return final;    

}

string unescapeString(string s) {

   string final = s;
   final = strReplace(final, "/c", ",");
   final = strReplace(final, "/l", "<");
   final = strReplace(final, "/r", ">");
   final = strReplace(final, "/s", " ");
   //backslash must be last when unescaping
   final = strReplace(final, "/b", "/");
   return final;

}


string List2TypeCSV(list input) { // converts a list to a CSV string with type information prepended to each item

   integer     i;
   list        output;
   integer     len;
   len=llGetListLength(input); //this can shave seconds off long lists
   for (i = 0; i < len; i++) {
       output += [llGetListEntryType(input, i)] + escapeString((string)llList2List(input, i, i));
   }
   
   return llList2CSV(output);

}

list TypeCSV2List(string inputstring) { // converts a CSV string created with List2TypeCSV back to a list with the correct type information

   integer     i;
   list        input;
   list        output;
   integer     len;
   
   input = llCSV2List(inputstring);
   len=llGetListLength(input);
   for (i = 0; i < len; i += 2) {
       string value = unescapeString(llList2String(input, i + 1));
       if (llList2Integer(input, i) == TYPE_INTEGER) output += (integer)value;
       else if (llList2Integer(input, i) == TYPE_FLOAT) output += (float)value;
       else if (llList2Integer(input, i) == TYPE_STRING) output += value;
       else if (llList2Integer(input, i) == TYPE_KEY) output += (key)value;
       else if (llList2Integer(input, i) == TYPE_VECTOR) output += (vector)value;
       else if (llList2Integer(input, i) == TYPE_ROTATION) output += (rotation)value;
   }
   
   return output;

}

testWithValue(string evilString) {

       list    l;
       string  s;
       
               l = [ 1, 2, evilString, 5 ];
       
       s = List2TypeCSV(l);
       
       l = TypeCSV2List(s);
       
       if (llGetListEntryType(l, 0) != TYPE_INTEGER) llOwnerSay("Bad! 0");
       if (llGetListEntryType(l, 1) != TYPE_INTEGER) llOwnerSay("Bad! 1");
       if (llGetListEntryType(l, 2) != TYPE_STRING) llOwnerSay("Bad! 2");
       if (llGetListEntryType(l, 3) != TYPE_INTEGER) llOwnerSay("Bad! 3");
       
       if (llList2Integer(l, 0) != 1) llOwnerSay("Bad! 0b");
       if (llList2Integer(l, 1) != 2) llOwnerSay("Bad! 1b");
       if (llList2String(l, 2) != evilString) llOwnerSay("Bad! 2b");
       if (llList2Integer(l, 3) != 5) llOwnerSay("Bad! 3b");

}

default {

   state_entry() {
       
       testWithValue("3,4");
       testWithValue("3<4");
       testWithValue("3>4");
       testWithValue("3/4");
       llOwnerSay("Done!");
   }

} </lsl>