June 7, 2012

Interobject Communications: lists

Lists contain values of varying types.  If llDumpListString() is used to create a text string which is to be sent as a message, then the value type information is irretrievably lost.

Preserve the type information by creating a new list in which the type code precedes each value.  The sender might have code like this:

    list a = [ ... some series of values ];
    list b = encodeList(a);
    llSay( commChannel, llDumpList2String( [ "listData", llGetListLength(b) ]
                               encodeList(b) + ["END"] , "|" );

The receiver might have code like this

listen( integer channel, string fromName, key fromKey, string msg ) {
    if ( channel == commChannel ) {
        list f = llParseStringKeepNulls( msg, "|" );
        if ( "listData" == llList2String(f,0) ) {
            if ( "END" != llList2String(f,-1) ) {
                ... tell some that the message has been truncated
            } else {
                integer n = (integer) llList2String(f,1);
                list dataList = [];
                if ( n > 0 ) {
                   dataList = decode( llList2List( f, 2, 1 + n );
                }
                n = llGetListLength(dataList);
                ........
            }
        }
     }
}

The encoder logic might be this

list typeList = [TYPE_FLOAT, TYPE_INTEGER, TYPE_KEY,
                   TYPE_ROTATION, TYPE_STRING, TYPE_VECTOR ];

list encodeTypeList( list a ) {
    list b = [];
    integer n = llGetListLength(a);
    integer k;  for ( k=0; k < n; k++ ) {
        integer type = llGetListEntryType(a,k);
        integer match = llListFindList( typeList, [type] );
        if ( match >= 0 ) {
            b += [type] + llList2List(a,k,k);
        } else llOwnerSay("** failed to match list entry type: "+(string)type);
    }
    return b;
}

The decoder logic might be this:

list decodeTypeList( list a ) {
    list b = [];
    integer n = llGetListLength(a);
    integer k;  for ( k=0; k < n; k += 2 ) {
        integer type = (integer) llList2String(a,k);
        string svalue = llList2String(a,k+1);
      
        integer match = llListFindList( typeList, [type] );
        if ( match >= 0 ) {
            if ( match-- == 0 )     b += (float) svalue;
            if ( match-- == 0 )     b += (integer) svalue;
            if ( match-- == 0 )     b += (key) svalue;
            if ( match-- == 0 )     b += (rotation) svalue;
            if ( match-- == 0 )     b += svalue;
            if ( match-- == 0 )     b += (vector) svalue;
        }
    }
    return b;
}

__________________

Notes:
  • When sending variable length lists, append "END" to the end of the message and have the receiver verify that it is still there.  There is a limit to the length of messages.
  • Include the encoded list length in the message, so that the receiver can extract the list.
  • Since lists may have zero length, the receiver should handle the zero length case.
[end]