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