[go: up one dir, main page]

Menu

[897c37]: / mlib / RO / lib / bag.lpc  Maximize  Restore  History

Download this file

313 lines (275 with data), 6.4 kB

/*
 *  Parsing bag object.
 *
 *  A bag is a 1 to many mapping of key to data.
 *
 *  setup(string savefile,int primesize, int start_new)  
 *  add(key, data) - 
 *  query(key) - 
 *  remove(key) -
 *
 *  save_me ()	  - usually called by save server
 *  show_stats () - returns the hash array (Just stat the object)
 *  dump_hash ()  - returns a pointer to the hash array,NOT a copy! 
 *
 *  20000507 Dredd Modified /RO/lib/dictionary
 */

inherit "RO/Servers";
inherit "RO/parse/parse_types";

import "RO/lib/dict_class" chash;

/* Key hash table vars */
class chash   hash_table[0];
int           hash_size;
static string save_file = 0;

/* Some accounting vars */
int no_items;
int no_neg_query;
int no_pos_query;


/*	 
 * Function : setup_hash (string file, int size, int start_new)  
 *
 *	Must be called first when you wish to use this object
 *	file: file name of where the data is to be stored.
 *		If you arnt going to save your data, file = 0
 *	size: needs to be used only once, when the hash table is set up.  
 *		should dynamically resize on day. (not supported initially)
 *	start_new: if you are going to set up a new hash data store. 
 *
 *	Returns 1 for success
 *
 */

int setup((string|int) file, int size, int start_new) 
{
	save_file = file;

	if (start_new) 
    {
	    if (file && (file_size (file + ".o") >= 0 
            || file_size (file + ".o.bak") >= 0 )) 
        {
		    throw("For safeties sake I dont want to overwrite the " +
                "old data file. Please make sure there is not a file named " +
                 file + ".\n");
		    return 0;
        }

        // already initialised.
        if (hash_size != 0) return 0;

	    hash_size = size;
	    hash_table = allocate(size);
        no_items = 0;
	    return 1;
	}
	else if (!restore_object(file,this_object())) 
    {
	    throw("Could not restore from save file.\n");
		return 0;
    }
	if (size && size != hash_size) 
    {
		/* Opps, dont match. add code for dynamic resizeing here! */
		throw("We dont currently support dynamic hash resizeing in the hash obj.\n");
		return 0;
	}
	return 1;
}

/*
 *	Name: add(key, data)
 *  Returns:
 */

int add(key, data)  
{
    array tmp;
    class chash incoming = create chash;
    class chash node;
    int hashpos;
    int x, dataoff;

	if (!hash_size) 
    {
		throw("The bag has not been initialised yet.\n");
		return 0;
	}

	incoming.key = key;
	incoming.data = [ data ];

	hashpos = hash_value(key) % hash_size;
	tmp = hash_table[hashpos];
	if (!tmp || sizeof(tmp) == 0) 
    {
	    hash_table[hashpos] = [ incoming ];
	}
	else 
    {
        /* check through existing nodes */
        for (x = 0; x < sizeof(tmp); x++)
        {
            node = tmp[x];
		    if (node.key == key) 
            {
                node.data = node.data + [ data ];
                dataoff = 1;
                break;
            }
        }

        /* doesn't exist so we add another */
        if (!dataoff) 
        {
            hash_table[hashpos] = tmp + [ incoming ];
        }
	}

	if (save_file) AUTOSAVE_SERV->set_auto_save(this_object());

    return 1;
}		 

/* 
 * Name: query(key)
 *
 *	Returns whatever was in the hash table, or 0 if nothing was there.
 *	last is a pointer to whatever data you searched for at hash_postition
 *	before and it returned another bit of data. This is a result
 *	of using a hash table and linked lists. 
 *
 */

query(key) 
{
    int pos, found = 0;
    int x;
    array nodel;
    class chash node;

	if (!hash_size) 
    {
		throw("The bag has not been initialised yet.\n");
		return 0;
	}

	pos = hash_value(key) % hash_size;
	nodel = hash_table[pos];
	if (nodel) 
    {
        for (x = 0; x < sizeof(nodel); x++)
        {
            node = nodel[x];
		    if (node.key == key) return node.data;
        }
	}
	return 0;
}

/*
 *	Function : remove_hash(key, data)
 *	Removes the data at the key position
 *
 */

remove(key, data) 
{
    int pos, found = 0;
    int x, i;
    array nodel, bag;
    class chash node;

	pos = hash_value(key) % hash_size;
	nodel = hash_table[pos];
	if (nodel) 
    {
        for (x = 0; x < sizeof(nodel); x++)
        {
            node = nodel[x];
		    if (node.key == key) 
            {
                bag = node.data;
                for (i = 0; i < sizeof(bag); i++)
                {   
                    if (bag[i] == data)
                    {
                        node.data = bag[..i-1] + bag[i+1..];
                        break;
                    }
                }
                AUTOSAVE_SERV->set_auto_save(this_object());
                return 1;
            }
        }
	}

	return 0;
}

erase(key)
{
    int pos, found = 0;
    int x, i;
    array nodel, bag;
    class chash node;

	pos = hash_value(key) % hash_size;
	nodel = hash_table[pos];
	if (nodel) 
    {
        for (x = 0; x < sizeof(nodel); x++)
        {
            node = nodel[x];
		    if (node.key == key) 
            {
                hash_table[pos] = hash_table[pos][..x-1] + hash_table[pos][x+1..];
                AUTOSAVE_SERV->set_auto_save(this_object());
                return 1;
            }
        }
	}

	return 0;
}

/*
 * Print out the data in some readable form
 */
out_data(x)
{
    int k;
    string od = "";

    if (arrayp(x))
    {
        od = od + "[";
        for (k = 0; k < sizeof(x); k++)
        {
            od = od + " " + out_data(x[k]);
        }
        od = od + "]";
        return od;
    }
    else if (objectp(x))
    {
        return file_name(x);
    }
    else
    {
        return x;
    }
}

/*
 * Standard "show_stats" function
 */
show_stats() 
{
    int i, j, k;
    array nodel;
    class chash node;

    for (i=0; i<hash_size; i++) 
    {
        nodel = hash_table[i];
        if (nodel) for (j = 0; j < sizeof(nodel); j++)
        {
            node = nodel[j];
            if (stringp(node.key))
            {
	            write("num("+i+","+j+"): "+(node.key)+ " = ");
                write(out_data(node.data) + "\n");
            }
        }
	}
    write("Save file is       : " + save_file + ".\n");
    write("No items in table   : "+ no_items +"\n");
    write("+ve queries / Total : "+ no_pos_query + "/" + (no_pos_query+
            no_neg_query) + "\n");
}

query_no_items() { return no_items; }

save_me () 
{
	save_object(save_file,this_object());
	return 1;
}

dump_hash() 
{
	return hash_table;
}

reset() 
{
}