Edinburgh Speech Tools  2.1-release
named_enum_example.cc
Go to the documentation of this file.
1  /************************************************************************/
2  /* */
3  /* Centre for Speech Technology Research */
4  /* University of Edinburgh, UK */
5  /* Copyright (c) 1996,1997 */
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: Richard Caley (rjc@cstr.ed.ac.uk) */
34  /* Date: Tue Apr 29 1997 */
35  /************************************************************************/
36  /* */
37  /* Example of the declaration and use fo the named enum type. */
38  /* */
39  /************************************************************************/
40 
41 #include <cstdlib>
42 #include <iostream>
43 #include "EST_TNamedEnum.h"
44 
45 using namespace std;
46 
47 #if defined(DATAC)
48 # define __STRINGIZE(X) #X
49 # define DATA __STRINGIZE(DATAC)
50 #endif
51 
52 // the named enum class provides an easy way to associate strings with
53 // the values of and enumerated type, for instance for IO. It's type safe and
54 // as readable as seems possible in C++.
55 
56 // A single enum element can have multiple names (eg synonyms or common typos)
57 
58 // Named enums are defined in terms of the more general valued enums which
59 // associates enum elements with members of an arbitrary type.
60 
61 // Both named enums and valued enums can have an additional piece of
62 // information (eg a struct containing creation functions or another
63 // representation) associated with each enum element.
64 
65 // --------- Declaration (eg in header or class) ------------
66 
67 // the enumerated type used in C code.
68 
69 typedef enum { c_red=1, c_blue=2, c_green=3, c_unknown=666} Colour;
70 
71 // the mapping used to get names and so on
73 
74 // ---------- Definition ---------------------------------------
75 // In a .C file somewhere we have to give the names in a table.
76 // The table has to be given a name and is then used to initialise the mapping.
77 
78 // The definition table ends with a repeat of the first entry and some
79 // value. This last pair gives the unknown enum value and unknown
80 // value for use when lookup fails
81 
82 // For reasons of C++ brain death we have to declare this as a
83 // ValuedEnumDefinition<X,const char *, NO_INFO> rather than a
84 // NamedEnum<X>::Definition or some other saner version
85 
87 // enum element list of names
88  { c_unknown, {"kinda brownish"},0},
89  { c_red, {"red", "scarlet"},0},
90  { c_blue, {"blue", "navy", "sad"},0},
91  { c_unknown, {NULL},0} // looking up unknown names gives c_unknown
92  // looking up unknown enum values gives NULL
93 End_TNamedEnum(Colour, ColourMap)
94 
95 // Here is a different table for the same enum type.
96 // Perhaps we want to accept input in Spanish, but not get Spanish and
97 // English names mixed up
98 
99 Start_TNamedEnum(Colour, SpanishColourMap)
100 // enum element list of names
101  { c_unknown, {"no conocido"},0},
102  { c_red, {"rojo", "escarlata", "sangre"},0},
103  { c_blue, {"azul", "piscina", "mar", "cielo"},0},
104  { c_unknown, {NULL},0}
105 End_TNamedEnum(Colour, SpanishColourMap)
106 
107 // ------- Alternative including extra information ---------------
108 
109 // Sometimes you may want to associate information with each element.
110 // The following variant associates three small integers with each
111 // colour, perhaps to enable them to be displayed.
112 
113 struct colour_info {
114  int red, green, blue;
115 };
116 
117 // a map including this extra information is declared as
119 
120 
121 // and here is how the values are defined.
122 
123 Start_TNamedEnumI(Colour, colour_info, RGBColourMap)
124 // enum element list of names extra info (red, green, blue)
125  { c_unknown, {"kinda grey"}, {0x7f, 0x7f, 0x7f}},
126  { c_red, {"red", "scarlet"}, {0xff, 0, 0}},
127  { c_blue, {"blue", "navy", "sad"}, {0, 0, 0xff}},
128  { c_unknown, {NULL},{0,0,0}}
129 End_TNamedEnumI(Colour, colour_info, RGBColourMap)
130 
131 
132 
133 // --------- Use -----------------------------------------------
134 
135 int main(void)
136 {
137  Colour c1 = c_red;
138  Colour c2 = c_green;
139  const char *n;
140 
141  // get the default name for colours.
142  n = ColourMap.name(c1);
143  cout << "c1 is " << (n?n:"[NULL]") << "\n";
144 
145  n = ColourMap.name(c2);
146  cout << "c2 is " << (n?n:"[NULL]") << "\n";
147 
148 
149  // look up some names to see what they correspond to
150  const char *colours[] = { "red", "navy", "puce"};
151  for(int i=0; i<3; i++)
152  {
153  // note since enum values are universal
154  // we can get the colour by assuming English, get the
155  // information from the other map and get the name for output in
156  // spanish
157  const char *nm= colours[i];
158  Colour c = ColourMap.token(nm);
159  colour_info &info = RGBColourMap.info(c);
160  const char *spanish = SpanishColourMap.name(c);
161 
162  cout << nm << " is " << (int)c
163  << " = " << ColourMap.name(c)
164  << " (" << (spanish?spanish:"[NULL]") << " in Spanish)"
165  << " = {"
166  << info.red << ", "
167  << info.green << ", "
168  << info.blue
169  << "}\n";
170  }
171 
172  // In the special case of EST_TNamedEnum (i.e. simple mappings from
173  // enum to (const char *) with no extra information) we can save
174  // mappings to files and read them back
175 
176  // There are two ways to save a mapping, we can have the file say how
177  // names map to numeric values...
178 
179  if (ColourMap.save("tmp/colour.map") != write_ok)
180  cout << "\n\nname map write failed\n";
181  else
182  {
183  cout << "\n\ncolour name map\n";
184  cout.flush();
185  if (system("cat tmp/colour.map") != 0) {
186  cerr << "Error printing file to screen" << endl;
187  exit(-1);
188  }
189  }
190 
191  // Of course this can result in the file not being valid when the
192  // enumerated type definition changes and so the assigned numbers change.
193 
194  // If there is a standard mapping defined and we are saving an
195  // alternative, the standard one can provide names for the enumerated
196  // values, meaning the file will be valid so long as the default
197  // mapping is correct.
198 
199  // For instance we can assume someone maintains the English names
200  // as the type is extended and save the Spanish names as a translation.
201 
202  if (SpanishColourMap.save("tmp/colour_spanish.map", ColourMap) != write_ok)
203  cout << "\n\nname map write failed\n";
204  else
205  {
206  cout << "\n\ncolour name map (spanish)\n";
207  cout.flush();
208  if (system("cat tmp/colour_spanish.map") != 0) {
209  cerr << "Error printing file to screen" << endl;
210  exit(-1);
211  }
212  }
213 
214  // There are two corresponding ways to read in a map.
215 
216  // If the map is defined in the file by numbers we load it like this...
217 
218  EST_TNamedEnum<Colour> LoadedColourMap(c_unknown);
219  if (LoadedColourMap.load(DATA "/colours.map") !=format_ok)
220  cout << "\n\nname map read failed\n";
221  else
222  {
223  cout << "\n\nread in table\n";
224  LoadedColourMap.save("tmp/tmp.map");
225  cout.flush();
226  if(system("cat tmp/tmp.map") != 0) {
227  cerr << "Error printing file to screen" << endl;
228  exit(-1);
229  }
230  }
231 
232  // If it's defined in the file using the names...
233 
234  if (LoadedColourMap.load(DATA "/colours_translation.map", ColourMap) !=format_ok)
235  cout << "\n\nname map read failed\n";
236  else
237  {
238  cout << "\n\nread in table (translation)\n";
239 
240  LoadedColourMap.save("tmp/tmp.map");
241  cout.flush();
242  if (system("cat tmp/tmp.map") != 0) {
243  cerr << "Error printing file to screen" << endl;
244  exit(-1);
245  }
246  }
247 
248  exit(0);
249 }
250 
251 // ----------- Template Brain Death --------------------
252 
253 // Declaration of the template use for GCC
254 // Just which variants need to be declared is sometimes unpredictable,
255 // especially between versions of gcc.
256 // Best just compile and then find out which ones aren't there.
257 
258 Declare_TNamedEnumI(Colour, colour_info)
260 
261 #if defined(INSTANTIATE_TEMPLATES)
262 #include "../base_class/EST_TNamedEnum.cc"
263 
264 Instantiate_TNamedEnumI(Colour, colour_info)
266 
267 #endif
#define End_TNamedEnum(ENUM, NAME)
#define End_TNamedEnumI(ENUM, INFO, NAME)
Start_TNamedEnum(Colour, ColourMap)
int main(int argc, char **argv)
Definition: align_main.cc:69
const char * name(ENUM tok, int n=0) const
The file was written successfully.
#define Declare_TNamedEnumI(ENUM, INFO)
EST_TNamedEnumI< Colour, colour_info > RGBColourMap
NULL
Definition: EST_WFST.cc:55
#define Instantiate_TNamedEnumI(ENUM, INFO)
getString int
Definition: EST_item_aux.cc:50
#define Declare_TNamedEnum(ENUM)
EST_read_status load(EST_String name)
#define format_ok
EST_TNamedEnum< Colour > ColourMap
EST_write_status save(EST_String name, char quote='"') const
#define Instantiate_TNamedEnum(ENUM)
Start_TNamedEnumI(Colour, colour_info, RGBColourMap)