Edinburgh Speech Tools  2.4-release
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends Pages
item_aux.cc
1 /*************************************************************************/
2 /* */
3 /* Centre for Speech Technology Research */
4 /* University of Edinburgh, UK */
5 /* Copyright (c) 1998 */
6 /* All Rights Reserved. */
7 /* */
8 /* Permission is hereby granted, free of charge, to use and distribute */
9 /* this software and its documentation without restriction, including */
10 /* without limitation the rights to use, copy, modify, merge, publish, */
11 /* distribute, sublicense, and/or sell copies of this work, and to */
12 /* permit persons to whom this work is furnished to do so, subject to */
13 /* the following conditions: */
14 /* 1. The code must retain the above copyright notice, this list of */
15 /* conditions and the following disclaimer. */
16 /* 2. Any modifications must be clearly marked as such. */
17 /* 3. Original authors' names are not deleted. */
18 /* 4. The authors' names are not used to endorse or promote products */
19 /* derived from this software without specific prior written */
20 /* permission. */
21 /* */
22 /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
23 /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24 /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25 /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
26 /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27 /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28 /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29 /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30 /* THIS SOFTWARE. */
31 /* */
32 /*************************************************************************/
33 /* Author : Alan W Black */
34 /* Date : May 1998 */
35 /*-----------------------------------------------------------------------*/
36 /* Various auxiliary item/relation functions for tree manipulation */
37 /* */
38 /*=======================================================================*/
39 #include <cstdlib>
40 #include <cstdio>
41 #include <iostream>
42 #include <fstream>
43 #include "ling_class/EST_Item.h"
44 #include "ling_class/EST_Item_Content.h"
45 #include "ling_class/EST_Relation.h"
46 
47 int in_list(const EST_Item *c,const EST_Item *l)
48 {
49  const EST_Item *i;
50 
51  for (i=l; i != 0; i=i->next())
52  if (i == c)
53  return TRUE;
54  return FALSE;
55 }
56 
57 int in_tree(const EST_Item *c,const EST_Item *t)
58 {
59  EST_Item *i;
60 
61  if (t == c)
62  return TRUE;
63  else
64  {
65  for (i=daughter1(t); i != 0; i=next_sibling(i))
66  if (in_tree(c,i))
67  return TRUE;
68  return FALSE;
69  }
70 }
71 
72 void remove_item_list(EST_Relation *rel, EST_Item *item)
73 {
74  if (item==NULL)
75  return;
76 
77  EST_Item *p = item->prev();
78  EST_Item *n = item->next();
79 
80  rel->remove_item(item);
81 
82  EST_Item::splice(p,n);
83 }
84 
85 int merge_item(EST_Item *from, EST_Item *to)
86 {
87  // Make all references to from be references to to and merge
88  // from's features into to
89  EST_Item *i;
90 
91  merge_features(to->features(),from->features());
92 
93  EST_Litem *r;
94  for (r = from->relations().list.head(); r; r=r->next())
95  {
96  i = item(from->relations().list(r).v);
97  if (i != from)
98  i->set_contents(to->contents());
99  }
100  from->set_contents(to->contents());
101 
102  return TRUE;
103 }
104 
105 void merge_features(EST_Item *to, EST_Item *from, int keep_id)
106 {
107  // Merge item features, but with option of preserving ids
108  EST_String keep;
109 
110  if (keep_id) keep = to->S("id", "0");
111  merge_features(to->features(),from->features());
112  if (keep_id) to->set("id", keep);
113 }
114 
115 int move_item(EST_Item *from, EST_Item *to)
116 {
117  // from's contents be to's contents, deleting from and all
118  // its daughters from to's relation.
119  EST_Item *rfrom = from->as_relation(to->relation_name());
120 
121  to->set_contents(from->contents());
122  if (rfrom != 0) // from is current in this relation
123  delete rfrom; // so delete it and its daughters
124 
125  return TRUE;
126 }
127 
128 int move_sub_tree(EST_Item *from, EST_Item *to)
129 {
130  // make from's contents be to's contents, delete all of to's
131  // daughters and rebuild from's descendants beneath to.
132  EST_Item *rfrom = from->as_relation(to->relation_name());
133  EST_Item *d,*r,*nr;
134 
135  if (in_tree(to,from))
136  return FALSE; // can't do that
137 
138  to->set_contents(from->contents());
139  // Remove current daughters, but don't delete them
140  // until after the copy in case from is within to's daughters
141  d = to->grab_daughters();
142  if (rfrom == d)
143  d = d->next();
144  if ((rfrom != 0) && (daughter1(rfrom)))
145  { // copy the descendant structure
146  copy_node_tree(daughter1(rfrom),to->insert_below(daughter1(rfrom)));
147  delete rfrom;
148  }
149  for (r=d; r; r=nr)
150  {
151  nr = r->next();
152  delete r;
153  }
154 
155  return TRUE;
156 }
157 
158 int exchange_sub_trees(EST_Item *from,EST_Item *to)
159 {
160  // Take contents of from and its daughters and replace
161  // them with contents of to and its daughters (and the reverse)
162  EST_Item *rfrom = from->as_relation(to->relation_name());
163 
164  if ((!rfrom) || (in_tree(rfrom,to)) || (in_tree(to,rfrom)))
165  return FALSE; // one or other in the other
166 
167  EST_Item_Content *toc = to->grab_contents();
168  EST_Item_Content *fromc = rfrom->grab_contents();
169  EST_Item *from_d = rfrom->grab_daughters();
170  EST_Item *to_d = to->grab_daughters();
171 
172  to->set_contents(fromc);
173  rfrom->set_contents(toc);
174  if (from_d)
175  copy_node_tree(from_d,to->insert_below(from_d));
176  if (to_d)
177  copy_node_tree(to_d,from->insert_below(to_d));
178 
179  return TRUE;
180 }
181 
182 
183 EST_Item *item_jump(EST_Item *from, const EST_String &to)
184 {
185  // This function jumps around standard festival relation structures.
186  // Designed to be fast rather than anything else.
187  // Behaviour is undefined for non standard structures.
188  // Gives the first of non-unique items.
189 
190  int f=0,t=0;
191 
192  if (to == "Segment")
193  t=1;
194  else if (to == "Syllable")
195  t=2;
196  else if (to == "Word")
197  t=3;
198  else if (to == "IntEvent")
199  t=4;
200 
201  if (from->in_relation("Segment"))
202  f=1;
203  else if (from->in_relation("Syllable"))
204  f=2;
205  else if (from->in_relation("Word"))
206  f=3;
207  else if (from->in_relation("IntEvent"))
208  f=4;
209 
210  if ( t == 0 || f == 0 )
211  return 0;
212 
213  if ( t == f )
214  return from;
215 
216  switch(f) {
217 
218  case 1:
219  // from Segment
220  switch(t) {
221  case 2:
222  // Syllable
223  return(from->as_relation("SylStructure")->up()->as_relation("Syllable"));
224  case 3:
225  // Word
226  return(from->as_relation("SylStructure")->up()->up()->as_relation("Word"));
227  case 4:
228  // IntEvent
229  return(from->as_relation("SylStructure")->up()->as_relation("Intonation")->down()->as_relation("IntEvent"));
230  }
231 
232  case 2:
233  // from Syllable
234  switch(t) {
235  case 1:
236  // Segment
237  return(from->as_relation("SylStructure")->down()->as_relation("Segment"));
238  case 3:
239  // Word
240  return(from->as_relation("SylStructure")->up()->as_relation("Word"));
241  // IntEvent
242  case 4:
243  return(from->as_relation("Intonation")->down()->as_relation("IntEvent"));
244  }
245 
246  case 3:
247  // from Word
248  switch(t) {
249  case 1:
250  // Segment
251  return(from->as_relation("SylStructure")->down()->down()->as_relation("Segment"));
252  case 2:
253  // Syllable
254  return(from->as_relation("SylStructure")->down()->as_relation("Syllable"));
255  case 4:
256  return(from->as_relation("SylStructure")->down()->as_relation("Intonation")->down()->as_relation("IntEvent"));
257  }
258 
259  case 4:
260  // from IntEvent
261  switch(t) {
262  case 1:
263  // Segment
264  return(from->as_relation("Intonation")->up()->as_relation("SylStructure")->down()->as_relation("Segment"));
265  case 2:
266  // Syllable
267  return(from->as_relation("Intonation")->up()->as_relation("Syllable"));
268  case 3:
269  // Word
270  return(from->as_relation("Intonation")->up()->as_relation("SylStructure")->up()->as_relation("Word"));
271  }
272  }
273 
274  return NULL;
275 }
276 
277 
278 
279 
280 
281 
282 
283 
284 
285