blob: dbecc90d62c90b0a7bf2093cc48eada7630777ff [file] [log] [blame]
/*************************************************************************/
/* */
/* Language Technologies Institute */
/* Carnegie Mellon University */
/* Copyright (c) 1999 */
/* All Rights Reserved. */
/* */
/* Permission is hereby granted, free of charge, to use and distribute */
/* this software and its documentation without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of this work, and to */
/* permit persons to whom this work is furnished to do so, subject to */
/* the following conditions: */
/* 1. The code must retain the above copyright notice, this list of */
/* conditions and the following disclaimer. */
/* 2. Any modifications must be clearly marked as such. */
/* 3. Original authors' names are not deleted. */
/* 4. The authors' names are not used to endorse or promote products */
/* derived from this software without specific prior written */
/* permission. */
/* */
/* CARNEGIE MELLON UNIVERSITY AND THE CONTRIBUTORS TO THIS WORK */
/* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
/* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
/* SHALL CARNEGIE MELLON UNIVERSITY NOR THE CONTRIBUTORS BE LIABLE */
/* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
/* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
/* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
/* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
/* THIS SOFTWARE. */
/* */
/*************************************************************************/
/* Author: Alan W Black (awb@cs.cmu.edu) */
/* Date: December 1999 */
/*************************************************************************/
/* */
/* Items (and Item Contents) */
/* */
/*************************************************************************/
#include "cst_alloc.h"
#include "cst_item.h"
#include "cst_relation.h"
#include "cst_utterance.h"
/* Define functions for using items, rels and utts as vals */
CST_VAL_REGISTER_TYPE_NODEL(relation,cst_relation)
CST_VAL_REGISTER_TYPE_NODEL(item,cst_item)
CST_VAL_REGISTER_TYPE(utterance,cst_utterance)
CST_VAL_REGISTER_FUNCPTR(itemfunc,cst_itemfunc)
cst_item *new_item_relation(cst_relation *r,cst_item *i)
{
cst_item *ni;
ni = cst_utt_alloc(r->utterance, cst_item, 1);
ni->contents = 0;
ni->n = ni->p = ni->u = ni->d = 0;
ni->relation = r;
item_contents_set(ni,i);
return ni;
}
void item_contents_set(cst_item *current, cst_item *i)
{
cst_item_contents *c = 0;
cst_item *nn_item;
if (i == 0)
c = new_item_contents(current);
else
c = i->contents;
if (c != current->contents)
{
item_unref_contents(current);
current->contents = c;
/* If this contents is already in this relation */
/* empty the other reference */
if (feat_present(current->contents->relations,current->relation->name))
{ /* oops this is already in this relation */
nn_item = val_item(feat_val(current->contents->relations,
current->relation->name));
feat_set(nn_item->contents->relations,
current->relation->name,
item_val(nn_item));
}
/* Add back reference */
feat_set(current->contents->relations,
current->relation->name,
item_val(current));
}
}
void delete_item(cst_item *item)
{
cst_item *ds, *nds;
if (item->n != NULL)
{
item->n->p = item->p;
item->n->u = item->u; /* in trees if this is first daughter */
}
if (item->p != NULL) item->p->n = item->n;
if (item->u != NULL) item->u->d = item->n; /* when first daughter */
if (item->relation)
{
if (item->relation->head == item)
item->relation->head = item->n;
if (item->relation->tail == item)
item->relation->tail = item->p;
}
/* Delete all the daughters of item */
for (ds = item->d; ds; ds=nds)
{
nds = ds->n;
delete_item(ds);
}
item_unref_contents(item);
cst_utt_free(item->relation->utterance, item);
}
void item_unref_contents(cst_item *item)
{
/* unreference this item from contents, and delete contents */
/* if no one else is referencing it */
if (item && item->contents)
{
feat_remove(item->contents->relations,item->relation->name);
if (feat_length(item->contents->relations) == 0)
{
delete_features(item->contents->relations);
delete_features(item->contents->features);
cst_utt_free(item->relation->utterance,item->contents);
}
item->contents = NULL;
}
}
cst_item_contents *new_item_contents(cst_item *i)
{
cst_item_contents *ic;
ic = cst_utt_alloc(i->relation->utterance,cst_item_contents,1);
ic->features = new_features_local(i->relation->utterance->ctx);
ic->relations = new_features_local(i->relation->utterance->ctx);
return ic;
}
cst_item *item_as(const cst_item *i,const char *rname)
{
/* return i as relation rname or null */
const cst_val *v;
if (i == NULL)
return NULL;
else
{
v = feat_val(i->contents->relations,rname);
if (v != NULL)
return val_item(v);
else
return NULL;
}
}
/********************************************************************/
/* List relation related functions */
/********************************************************************/
cst_item *item_next(const cst_item *i)
{
if (i == NULL)
return NULL;
else
return i->n;
}
cst_item *item_prev(const cst_item *i)
{
if (i == NULL)
return NULL;
else
return i->p;
}
cst_item *item_append(cst_item *current, cst_item *ni)
{
cst_item *rni = 0;
if (ni && (ni->relation == current->relation))
{
/* got to delete it first as an item can't be in a relation twice */
}
else
rni = new_item_relation(current->relation,ni);
rni->n = current->n;
if (current->n != NULL)
current->n->p = rni;
rni->p = current;
current->n = rni;
if (current->relation->tail == current)
current->relation->tail = rni;
return rni;
}
cst_item *item_prepend(cst_item *current, cst_item *ni)
{
cst_item *rni = 0;
if (ni && (ni->relation == current->relation))
{
/* got to delete it first as an item can't be in a relation twice */
}
else
rni = new_item_relation(current->relation,ni);
rni->p = current->p;
if (current->p != NULL)
current->p->n = rni;
rni->n = current;
current->p = rni;
if (current->u) /* in a tree */
{
current->u->d = rni;
rni->u = current->u;
current->u = NULL;
}
if (current->relation->head == current)
current->relation->head = rni;
return rni;
}
/********************************************************************/
/* Tree relation related functions */
/********************************************************************/
cst_item *item_parent(const cst_item *i)
{
const cst_item *n;
for (n=i; item_prev(n); n=item_prev(n));
if (n == NULL)
return NULL;
else
return n->u;
}
cst_item *item_daughter(const cst_item *i)
{
if (i == NULL)
return NULL;
else
return i->d;
}
cst_item *item_nth_daughter(const cst_item *i,int n)
{
int d;
cst_item *p;
for (d=0,p=item_daughter(i); p && (d < n); p=item_next(p),d++);
return p;
}
cst_item *item_last_daughter(const cst_item *i)
{
cst_item *p;
for (p=item_daughter(i); item_next(p); p=item_next(p));
return p;
}
cst_item *item_add_daughter(cst_item *i,cst_item *nd)
{
cst_item *p,*rnd;
p = item_last_daughter(i);
if (p)
rnd=item_append(p,nd);
else
{ /* first new daughter */
if (nd && (nd->relation == i->relation))
{
/* got to delete it first as nd can't be in a relation twice */
cst_errmsg("item_add_daughter: already in relation\n");
return 0;
}
else
rnd = new_item_relation(i->relation,nd);
rnd->u = i;
i->d = rnd;
}
return rnd;
}
/********************************************************************/
/* Feature functions */
/********************************************************************/
int item_feat_present(const cst_item *i,const char *name)
{
return feat_present(item_feats(i),name);
}
int item_feat_remove(const cst_item *i,const char *name)
{
return feat_remove(item_feats(i),name);
}
cst_features *item_feats(const cst_item *i)
{
return (i ? i->contents->features : NULL);
}
const cst_val *item_feat(const cst_item *i,const char *name)
{
return feat_val(item_feats(i),name);
}
int item_feat_int(const cst_item *i,const char *name)
{
return feat_int(item_feats(i),name);
}
float item_feat_float(const cst_item *i,const char *name)
{
return feat_float(item_feats(i),name);
}
const char *item_feat_string(const cst_item *i,const char *name)
{
return feat_string(item_feats(i),name);
}
void item_set(const cst_item *i,const char *name,const cst_val *val)
{
feat_set(item_feats(i),name,val);
}
void item_set_int(const cst_item *i,const char *name,int val)
{
feat_set_int(item_feats(i),name,val);
}
void item_set_float(const cst_item *i,const char *name,float val)
{
feat_set_float(item_feats(i),name,val);
}
void item_set_string(const cst_item *i,const char *name,const char *val)
{
feat_set_string(item_feats(i),name,val);
}
cst_utterance *item_utt(const cst_item *i)
{
if (i && i->relation)
return i->relation->utterance;
else
return NULL;
}
int item_equal(const cst_item *a, const cst_item *b)
{
if ((a == b) ||
(a && b && (a->contents == b->contents)))
return TRUE;
else
return FALSE;
}