ref: c5bd2add37725041c1924132a8a4fd67548fb975
dir: /src/hrg/cst_item.c/
/*************************************************************************/ /* */ /* 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_first(const cst_item *i) { cst_item *p; for (p=(cst_item *)(void *)i; item_prev(p); p=item_prev(p)); return p; } cst_item *item_last(const cst_item *i) { cst_item *p; for (p=(cst_item *)(void *)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; }