User:Decimus Schomer/Scripts/Libraries/LSL sets

From The SchomEmunity Wiki
Jump to: navigation, search

Decimus' user page | Decimus' talk page | Decimus' scripts | Decimus' script libraries | Decimus' projects
Main script library page | LSL MDAs | LSL Sets


Script

// LSL set library
// Copyright (C) 2007 Decimus Schomer
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

// (you can find version 2 of the GPL at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html)

////////////////////////////////////////////////////////////////////////////////
// Multi-dimensional array library (required for multi-dimensional sets)

list mda_val_lens;
list mda_val;

integer mda_len(integer idx)
{
    if (idx == -1)
        return llGetListLength(mda_val_lens);
    return llList2Integer(mda_val_lens, idx);
}

////////////////////////////////////////////////////////////////////////////////
// Set library

list set_add(list set, list val)
{
    if(val != [0]) // Only want single entry lists. (Comparing lists compares list length; comparison is faster than length checking)
    {
        llSay(DEBUG_CHANNEL,"set_add: Adding too many sets at once!");
        return set;
    }
    if(!~llListFindList(set,val))
    {
        set = (set=[])+set+val;
    }
    return set;
}

set_add_list(list val)
{
    integer lenv = llGetListLength(val);
    string csvv = llList2CSV(val);
    integer x;
    integer y;
    list l;
    integer s = 0;
    integer d;
    integer mlen = mda_len(-1);
    for (y = 0; y < mlen; ++y)
    {
        d = llList2Integer(mda_val_lens, y);
        if (d == lenv)
        {
            l = llList2List(mda_val, s, s+d);
            for (x = 0; x < d; ++x)
            {
                // It's safe to compare anything as a string, excluding floats that you want accurate to more than six significant figures.
                // You can't really compare those anyway.
                if (llList2CSV(l) == csvv)
                {
                    return;
                }
            }
        }
        s += d;
    }
    mda_val += val;
    mda_val_lens += [lenv];
}

list list_to_set(list l)
{
    list copy = [];
    integer i;
    integer len = llGetListLength(l);
    for (i = 0; i < len; ++i)
    {
        if(llGetListEntryType(l, i) == TYPE_INTEGER)
        {
            copy = set_add_int(copy, llList2Integer(l, i));
        }
        else if(llGetListEntryType(l, i) == TYPE_STRING)
        {
            copy = set_add_str(copy, llList2String(l, i));
        }
    }
    return copy;
}

mda_to_set()
{
    integer len = mda_len(-1);
    list orig_lens = mda_val_lens;
    list orig = mda_val;
    mda_val_lens = [];
    mda_val = [];
    integer i;
    integer s;
    integer d;
    list l;
    for (i = 0; i < len; ++i)
    {
        d = llList2Integer(orig_lens, i);
        l = llList2List(orig, s, s+d);
        set_add_list(l);
        s += d;
    }
}

// Compatability functions
set_add_int_list(list val)
{
    set_add_list(val);
}

set_add_str_list(list val)
{
    set_add_list(val);
}

list int_list_to_set(list l)
{
    return list_to_set(l);
}

list str_list_to_set(list l)
{
    return list_to_set(l);
}

str_mda_to_set()
{
    mda_to_set();
}

int_mda_to_set()
{
    mda_to_set();
}

list set_add_int(list set, integer val)
{
    return set_add(set,[val]);
}

list set_add_str(list set, string val)
{
    return set_add(set,[val]);
}

Usage

Put this script at the start of any script requiring sets. Then, make a normal list (sets are just lists but with specific functions used to update them) and, to append an item, instead of putting l += [1], put set_add_int(l, 1) or the equivalent for whatever other type you're using (and, to convert a list to a set, put int_list_to_set(l) or the equivalent for a different type)

To use multi-dimensional sets, you need to use mda_val and mda_val_lens in the same way as you would for the functions in the MDA library.

Note: I've moved the comments to the Talk page, so please put any other comments on there