Skip to content

Commit

Permalink
Added a dictionary abstract data type. Currently it's implemented as
Browse files Browse the repository at this point in the history
Estimated hours taken: 2

Added a dictionary abstract data type. Currently it's implemented as
a dirt-simple ordered list, but it should later be reimplemented using a
hash table. Note that C has only very poor support for ADTs
and private data must be included in the header. We trust clients
of the ADT not to use the private data.

bytecode/dict.h:
	Interface of dictionary ADT.
bytecode/dict.c:
	Implementation of dictionary ADT.
  • Loading branch information
Bert Thompson committed May 28, 1997
1 parent 7f1d65c commit 06454f7
Show file tree
Hide file tree
Showing 2 changed files with 244 additions and 0 deletions.
161 changes: 161 additions & 0 deletions bytecode/dict.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@

/*
** Copyright (C) 1997 University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
**
** $Id: dict.c,v 1.1 1997-05-28 05:58:55 aet Exp $
*/

/* Imports */
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>

#include "mem.h"
#include "util.h"

#include "dict.h"

/* Exported definitions */

/* Local declarations */

static char
rcs_id[] = "$Id: dict.c,v 1.1 1997-05-28 05:58:55 aet Exp $";

static p_Dict_Item *
insert(KeyComparison cmp, void *key, void *val, p_Dict_Item *items);

static MB_Bool
lookup(KeyComparison cmp, void *key, p_Dict_Item *items, void **val_p);

static p_Dict_Item *
delete(KeyComparison cmp, void *key, p_Dict_Item *items);

static p_Dict_Item *
new_item_p(void *key, void *val, p_Dict_Item* next);

/* Implementation */

/*
** XXX: Yes, this implementation is hopelessly inefficient.
** I'll replace it with a hash table when things are working.
*/

Dict
dict_new(KeyComparison key_cmp)
{
Dict *new_dict_p;

new_dict_p = (Dict*) MB_malloc(sizeof(Dict));

new_dict_p->p_key_cmp = key_cmp;
new_dict_p->p_items = NULL;

return *new_dict_p;
}

void
dict_insert(void *key, void *val, Dict *dict_p)
{
assert(dict_p != NULL);
assert(dict_p->p_key_cmp != NULL);

dict_p->p_items = insert(dict_p->p_key_cmp, key, val, dict_p->p_items);
}

/*
** Insert items in ascending order sorted on keys.
*/
static p_Dict_Item *
insert(KeyComparison cmp, void *key, void *val, p_Dict_Item *items)
{
if (items == NULL) {
return new_item_p(key, val, NULL);
} else if (cmp(key, items->p_key) < 0) {
return new_item_p(key, val, items);
} else if (cmp(key, items->p_key) > 0) {
items->p_next = insert(cmp, key, val, items->p_next);
return items;
} else { /* keys are same */
items->p_val = val;
return items;
}
}

MB_Bool
dict_lookup(void *key, Dict dict, void **val_p)
{
assert (dict.p_key_cmp != NULL);
return lookup(dict.p_key_cmp, key, dict.p_items, val_p);
}

static MB_Bool
lookup(KeyComparison cmp, void *key, p_Dict_Item *items, void **val_p)
{
p_Dict_Item *cur;

cur = items;

while (TRUE) {
if (cur == NULL) {
return FALSE;
} else if (cmp(cur->p_key,key) == 0) {
*val_p = cur->p_val;
return TRUE;
} else {
cur = cur->p_next;
}
}
}

void
dict_delete(void *key, Dict *dict_p)
{
assert(dict_p != NULL);
assert(dict_p->p_key_cmp != NULL);

dict_p->p_items = delete(dict_p->p_key_cmp, key, dict_p->p_items);
return;
}

static p_Dict_Item *
delete(KeyComparison cmp, void *key, p_Dict_Item *items)
{
if (items == NULL) {
return NULL;
} else if (cmp(key,items->p_key) == 0) {
/*
** XXX: Use Boehm GC to collect garbage node.
*/
return items->p_next;
} else {
p_Dict_Item *new_items;

items->p_next = delete(cmp, key, items->p_next);
return items;
}
}


KeyComparison
dict_key_compare(Dict dict)
{
return dict.p_key_cmp;
}

static p_Dict_Item *
new_item_p(void *key, void *val, p_Dict_Item* next)
{
p_Dict_Item *item_p;

item_p = (p_Dict_Item*) MB_malloc(sizeof(p_Dict_Item));

item_p->p_key = key;
item_p->p_val = val;
item_p->p_next = next;

assert(item_p != NULL);
return item_p;
}
83 changes: 83 additions & 0 deletions bytecode/dict.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
** Copyright (C) 1997 University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
**
** $Id: dict.h,v 1.1 1997-05-28 05:58:59 aet Exp $
*/


#ifndef MB_DICT_H
#define MB_DICT_H

/*
** A simple abstract data type for a key-value dictionary.
**
** Note that this type is ABSTRACT. Client code must not refer to
** any types or fields prefixed with "p_" since they are private
** (part of the implementation, not of the interface) and may be
** changed or removed if the implementation changes. ADTs in C
** are never pretty.
**
** Given how slow the current implementation is, you can be sure
** it will change.
**
** Note: The "_p" -suffix- denotes a pointer, not a private type or data.
*/

typedef int (*KeyComparison)(const void *, const void *);

typedef struct p_Dict_Item {
void *p_key;
void *p_val;
struct p_Dict_Item *p_next;
} p_Dict_Item;


typedef struct Dict {
KeyComparison p_key_cmp;
p_Dict_Item *p_items;
} Dict;

/*
** Create a new dictionary that uses a given comparison function.
** The comparsion function works like strcmp. Specifically, key_cmp(x1,x2)
** returns negative if x1 < x2, zero if x1==x2, positive if x1>x2.
** XXX: Should also pass in some sort of string to identify the dictionary?
*/
Dict
dict_new(KeyComparison key_cmp);

/*
** Insert key-value pair into dictionary.
*/
void
dict_insert(void *key, void *val, Dict *dict_p);

/*
** Lookup value corresponding to key. Returns TRUE if lookup succeeded,
** FALSE if it failed.
*/
MB_Bool
dict_lookup(void *key, Dict dict, void **val_p);

/*
** Delete key-value pair corresponding to key.
*/
void
dict_delete(void *key, Dict *dict_p);

/*
** Return the key comparison function used by a dictionary.
*/
KeyComparison
dict_key_compare(Dict dict);

/*
** XXX: Need another function to allow us to iterate through the
** contents of a dictionary.
*/

#endif /* MB_DICT_H */


0 comments on commit 06454f7

Please sign in to comment.