Edinburgh Speech Tools  2.4-release
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends Pages
EST_features_io.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 : March 1998 */
35 /*-----------------------------------------------------------------------*/
36 /* Features i/o */
37 /* This is kept separate from EST_Features to help reduce dependencies */
38 /*=======================================================================*/
39 #include <cstdlib>
40 #include "EST_Features.h"
41 #include "ling_class/EST_Item.h"
42 #include "EST_error.h"
43 #include "EST_String.h"
44 #include "EST_Token.h"
45 
47  const EST_String &funcname)
48 {
49  EST_Item_featfunc f = get_featfunc(funcname,1);
50 
51  set_path(name, est_val(f));
52 }
53 
54 void EST_Features::save_fpair(ostream &outf,
55  const EST_String &fname,
56  const EST_Val &fvalue) const
57 {
58  /* Feature valued features themselves (so can't denot empty ones) */
59  if (fvalue.type() == val_type_feats)
60  {
61  EST_Features *f = feats(fvalue);
62  if (f->features->list.head() == 0)
63  {
64  // An empty feature set
65  outf << fname << " () ; ";
66  }
67  else
68  for (EST_Litem *q=f->features->list.head();
69  q != 0; q=q->next() )
70  save_fpair(outf,
71  fname+"."+f->features->list(q).k,
72  f->features->list(q).v);
73  return;
74  }
75  /* a non feature valued one */
76  // in case someone has () in their feature names (ought to be shot)
77  if (fname.contains("(") ||
78  fname.contains(")") ||
79  fname.contains(" ") || // bang, bang
80  fname.contains("\t") || // what smoking gun ?
81  fname.contains(";") ||
82  (fname == ""))
83  outf << quote_string(fname,"\"","\\",1) << " ";
84  else
85  outf << fname << " ";
86  if (fvalue == ";")
87  outf << "\";\"";
88  else if ((fvalue.type() == val_string) &&
89  ((fvalue.string().matches(RXint)) ||
90  (fvalue.string().matches(RXdouble)) ||
91  (fvalue.string().contains("(")) ||
92  (fvalue.string().contains(")")) ||
93  (fvalue.string().contains(";")) ))
94  // force quoting, cause it looks like a number but isn't
95  outf << quote_string(fvalue.string(),"\"","\\",1);
96  else if (fvalue.type() == val_float)
97  {
98  char b[20];
99  sprintf(b,"%g",fvalue.Float());
100  outf << b;
101  }
102  else if (fvalue.type() == val_type_featfunc)
103  {
104  outf << "F:"<<get_featname(featfunc(fvalue));
105  }
106  else
107  outf << quote_string(fvalue.string());
108  outf << " ; ";
109 }
110 
111 EST_write_status EST_Features::save(ostream &outf) const
112 {
113  // Save features
114  if (features->list.head() == 0)
115  outf << "()";
116  else
117  for (EST_Litem *p=features->list.head(); p != 0; p=p->next() )
118  save_fpair(outf,
119  features->list(p).k,
120  features->list(p).v);
121 
122  return write_ok;
123 }
124 
125 EST_write_status EST_Features::save_sexpr(ostream &outf) const
126 {
127  // Save features as an sexpression
128  outf << "(";
129  for (EST_Litem *p=features->list.head(); p != 0; p=p->next() )
130  {
131  const EST_String &fname = features->list(p).k;
132  const EST_Val &fvalue = features->list(p).v;
133  outf << "(";
134  // in case someone has () in their feature names (ought to be shot)
135  if (fname.contains("(") ||
136  fname.contains(")") ||
137  fname.contains(" ") ||
138  fname.contains("\t") ||
139  fname.contains(";"))
140  outf << quote_string(fname,"\"","\\",1);
141  else
142  outf << fname;
143  outf << " ";
144  if (fvalue == ";")
145  outf << "\";\"";
146  else if ((fvalue.type() == val_string) &&
147  ((fvalue.string().matches(RXint)) ||
148  (fvalue.string().matches(RXdouble)) ||
149  (fvalue.string().contains("(")) ||
150  (fvalue.string().contains(")"))))
151  // force quoting, cause it looks like a number but isn't
152  // or contains a paren
153  outf << quote_string(fvalue.string(),"\"","\\",1);
154  else if (fvalue.type() == val_float)
155  {
156  char b[20];
157  sprintf(b,"%g",fvalue.Float());
158  outf << b;
159  }
160  else if (fvalue.type() == val_type_featfunc)
161  {
162  outf << "F:"<<get_featname(featfunc(fvalue));
163  }
164  else if (fvalue.type() == val_type_feats)
165  {
166  feats(fvalue)->save_sexpr(outf);
167  }
168  else
169  outf << quote_string(fvalue.string());
170  outf << ")";
171  if (p->next())
172  outf << " ";
173  }
174  outf << ")";
175 
176  return write_ok;
177 }
178 
180 {
181  /* Load in feature structure from sexpression */
182 
183  if (ts.peek() != "(")
184  {
185  cerr << "load_features: no sexpression found\n";
186  return misc_read_error;
187  }
188  else
189  {
190  EST_String f;
191  EST_Token v;
192  ts.get(); /* skip opening paren */
193  for (; ts.peek() != ")"; )
194  {
195  if (ts.peek() != "(")
196  {
197  cerr << "load_features: no sexpression found\n";
198  return misc_read_error;
199  }
200  ts.get();
201  f = ts.get().string(); /* feature name */
202  if ((ts.peek() == "(") && (ts.peek().quoted() == FALSE))
203  {
204  EST_Features fv;
205  set(f,fv);
206  A(f).load_sexpr(ts);
207  }
208  else
209  {
210  v = ts.get();
211  if (v.quoted())
212  set(f,v.string());
213  else if (v.string().matches(RXint))
214  set(f,atoi(v.string()));
215  else if (v.string().matches(RXdouble))
216  set(f,atof(v.string()));
217  else if (v.string().contains("F:"))
218  {
219  EST_Item_featfunc func =
220  get_featfunc(v.string().after("F:"));
221  if (func != NULL)
222  set_val(f,est_val(func));
223  else
224  {
225  cerr << "load_features: Unknown Function '" << f <<"'\n";
226  set_val(f,feature_default_value);
227  }
228  }
229  else
230  set(f,v.string());
231 
232  }
233  if (ts.get() != ")")
234  {
235  cerr << "load_features: no sexpression found\n";
236  return misc_read_error;
237  }
238  }
239  if (ts.get() != ")")
240  {
241  cerr << "load_features: no sexpression found\n";
242  return misc_read_error;
243  }
244  }
245  return format_ok;
246 }
247 
249 {
250  // load features from here to end of line separated by semicolons
251  EST_String f;
252  EST_Token v;
253  static EST_Val val0 = EST_Val(0);
254 
255  while (!ts.eoln())
256  {
257  if (ts.eof())
258  {
259  cerr << "load_features: unexpected end of file\n";
260  return misc_read_error;
261  }
262  f = ts.get().string();
263  v = EST_String::Empty;
264  while (((ts.peek() != ";") || (ts.peek().quoted())) &&
265  (!ts.eof()) && (!ts.eoln()))
266  if (v == "")
267  v = ts.get();
268  else
269  v = v.string()
270  + ts.peek().whitespace()
271  + ts.get().string();
272  if (v.quoted() || (v.string() == ""))
273  set_path(f,EST_Val(v.string()));
274  else if (v.string() == "0") // very common cases for speed
275  set_path(f,val0);
276  else if ((strchr("0123456789-.",v.string()(0)) != NULL) &&
277  (v.string().matches(RXdouble)))
278  {
279  if (v.string().matches(RXint))
280  set_path(f, EST_Val(atoi(v.string())));
281  else
282  set_path(f, EST_Val(atof(v.string())));
283  }
284  else if (v.string().contains("F:"))
285  {
286  EST_Item_featfunc func = get_featfunc(v.string().after("F:"));
287  if (func != NULL)
288  set_path(f, est_val(func));
289  else
290  {
291  cerr << "load_features: Unknown Function '" << f <<"'\n";
292  set_path(f, feature_default_value);
293  }
294  }
295  else if (v.string() == "()")
296  { // An empty feature set
297  EST_Features *fs = new EST_Features;
298  set_path(f,est_val(fs));
299  }
300  else if (v != "<contents>") // unsupported type
301  set_path(f,EST_Val(v.string()));
302  if (ts.peek() == ";")
303  ts.get();
304  else if (!ts.eoln())
305  {
306  cerr << "load_features: " << ts.pos_description() <<
307  " missing semicolon in feature list\n";
308  return misc_read_error;
309  }
310  }
311  return format_ok;
312 }
313