1 /*************************************************************************/
2 /*                                                                       */
3 /*                Centre for Speech Technology Research                  */
4 /*                     University of Edinburgh, UK                       */
5 /*                      Copyright (c) 1995,1996                          */
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 :  Paul Taylor                            */
34 /*                      Date   :  May 1995                               */
35 /*-----------------------------------------------------------------------*/
36 /*                 Key/value List Class source file                      */
37 /*                                                                       */
38 /*=======================================================================*/
39 
40 #include <cstdlib>
41 #include "EST_TKVL.h"
42 #include "EST_error.h"
43 
EST_TKVL(const EST_TKVL<K,V> & kv)44 template <class K, class V> EST_TKVL<K, V>::EST_TKVL(const EST_TKVL<K, V> &kv)
45 {
46     list = kv.list;
47 }
48 
49 template <class K, class V>
clear(void)50 void EST_TKVL<K, V>::clear(void)
51 {
52     list.clear();
53 }
54 
55 template <class K, class V>
find_pair_key(const K & key) const56 EST_Litem *EST_TKVL<K, V>::find_pair_key(const K &key) const
57 {
58     EST_Litem *ptr;
59 
60     for (ptr = list.head(); ptr != 0; ptr= ptr->next())
61 	if (list.item(ptr).k == key)
62 	    return ptr;
63     return 0;
64 }
65 
66 template <class K, class V>
find_pair_val(const V & val) const67 EST_Litem *EST_TKVL<K, V>::find_pair_val(const V &val) const
68 {
69     EST_Litem *ptr;
70 
71 ///    cout << "function list\n" << endl;
72 
73     for (ptr = list.head(); ptr != 0; ptr= ptr->next())
74     {
75 //	cout << "ff: " << list.item(ptr).k << endl;
76 	if (list.item(ptr).v == val)
77 	    return ptr;
78     }
79     return 0;
80 }
81 
82 
83 // look for pointer kptr in list. If found, change its value to rval and
84 // return true, otherwise return false.
85 
86 template <class K, class V>
change_val(EST_Litem * kptr,const V & rval)87 int EST_TKVL<K, V>::change_val(EST_Litem *kptr, const V &rval)
88 {
89     if (list.index(kptr) == -1)
90 	return 0;
91     else
92     {
93 	list.item(kptr).v = rval;
94 	return 1;
95     }
96 }
97 
98 template <class K, class V>
change_key(EST_Litem * kptr,const K & rkey)99 int EST_TKVL<K, V>::change_key(EST_Litem *kptr, const K &rkey)
100 {
101     if (list.index(kptr) == -1)
102 	return 0;
103     else
104     {
105 	list.item(kptr).k = rkey;
106 	return 1;
107     }
108 }
109 
110 // look for key rkey in list. If found, change its value to rval and
111 // return true, otherwise return false.
112 template <class K, class V>
change_val(const K & rkey,const V & rval)113 int EST_TKVL<K, V>::change_val(const K &rkey,const V &rval)
114 {
115     EST_Litem *ptr=find_pair_key(rkey);
116     if (ptr == 0)
117 	return 0;
118     else
119     {
120 	list.item(ptr).v = rval;
121 	return 1;
122     }
123 }
124 
125 // NOTE: This _MUST_NOT_ change the EST_TKVL,  if it needs to, a separate
126 // const version will need to replace the dummy one below.
127 
128 template<class K, class V>
val(const K & rkey,bool must)129 V &EST_TKVL<K, V>::val(const K &rkey, bool must)
130 {
131     EST_Litem *ptr = find_pair_key(rkey);
132 
133     if (ptr == 0)
134     {
135 	if (must)
136 	  EST_error("No value set for '%s'", error_name(rkey));
137 
138 	return *default_val;
139     }
140     else
141 	return list.item(ptr).v;
142 }
143 
144 template<class K, class V>
val(const K & rkey,bool must) const145 const V &EST_TKVL<K, V>::val(const K &rkey, bool must) const
146 {
147    return ((EST_TKVL<K, V> *)this)->val(rkey, must);
148 }
149 
150 template<class K, class V>
val_def(const K & rkey,const V & def) const151 const V &EST_TKVL<K, V>::val_def(const K &rkey, const V &def) const
152 {
153     EST_Litem *ptr = find_pair_key(rkey);
154     if (ptr == 0)
155 	return def;
156     else
157 	return list.item(ptr).v;
158 }
159 
160 // NOTE: This _MUST_NOT_ change the EST_TKVL,  if it needs to, a separate
161 // const version will need to replace the dummy one below.
162 
163 template<class K, class V>
val(EST_Litem * kptr,bool must)164 V &EST_TKVL<K, V>::val(EST_Litem *kptr, bool must)
165 {
166     if (must == 0)
167 	return list.item(kptr).v;
168     /* check kptr is one of mine */
169     if (list.index(kptr) == -1)
170     {
171       if (must)
172 	EST_error("No value set in EST_TKVL");
173       return *default_val;
174     }
175     else
176 	return list.item(kptr).v;
177 }
178 
179 
180 template<class K, class V>
val(EST_Litem * kptr,bool must) const181 const V &EST_TKVL<K, V>::val(EST_Litem *kptr, bool must) const
182 {
183   return ((EST_TKVL<K, V> *)this)->val(kptr, must);
184 }
185 
186 // NOTE: This _MUST_NOT_ change the EST_TKVL,  if it needs to, a separate
187 // const version will need to replace the dummy one below.
188 
189 template<class K, class V>
190 K &EST_TKVL<K, V>::key(EST_Litem *kptr, int must)
191 {
192     if (must == 0)
193 	return list.item(kptr).k;
194     if (list.index(kptr) == -1)
195       EST_error("No value set in EST_TKVL");
196 
197     return list.item(kptr).k;
198 }
199 
200 template<class K, class V>
key(EST_Litem * kptr,int must) const201 const K &EST_TKVL<K, V>::key(EST_Litem *kptr, int must) const
202 {
203   return ((EST_TKVL<K, V> *)this)->key(kptr, must);
204 }
205 
206 template<class K, class V>
key(const V & v,int must) const207 const K &EST_TKVL<K, V>::key(const V &v, int must) const
208 {
209     EST_Litem *ptr = find_pair_val(v);
210     if (ptr == 0)
211     {
212 	if (must)
213 	  EST_error("No value set for '%s'", error_name(v));
214 
215 	return *default_key;
216     }
217 
218     return list.item(ptr).k;
219 }
220 
221 template<class K, class V>
present(const K & rkey) const222 const int EST_TKVL<K, V>::present(const K &rkey) const
223 {
224     if (find_pair_key(rkey) == 0)
225 	return 0;
226     else
227 	return 1;
228 }
229 
230 // map a function over the pairs
231 
232 template<class K, class V>
map(void (* func)(K &,V &))233 void EST_TKVL<K,V>::map(void (*func)(K&, V&))
234 {
235     EST_Litem *p;
236     for(p=list.head(); p; p=p->next())
237     {
238 	EST_TKVI<K,V> item = list.item(p);
239 	(*func)(item.k, item.v);
240     }
241 }
242 
243 // add item to list. By default, the list is searched to see if the
244 // item exists already. If so, its value is overwritten. This facility
245 // can be turned off by setting no_search = 1;
246 
247 template<class K, class V>
add_item(const K & rkey,const V & rval,int no_search)248 int EST_TKVL<K, V>::add_item(const K &rkey, const V &rval, int no_search)
249 {
250     if (!no_search)
251 	if (change_val(rkey, rval)) // first see if key exists
252 	    return 1;
253 
254     EST_TKVI<K,V>  item;
255     item.k = rkey;
256     item.v = rval;
257 
258     list.append(item);
259     return 1;
260 }
261 
262 template<class K, class V>
remove_item(const K & rkey,int quiet)263 int EST_TKVL<K, V>::remove_item(const K &rkey, int quiet)
264 {
265     EST_Litem *ptr = find_pair_key(rkey);
266     const char *en;
267     if (ptr == 0)
268     {
269 	if (!quiet)
270 	{
271 	    en = error_name(rkey);
272 	    EST_warning("EST_TKVL: no item labelled '%s'", en);
273 	}
274 	return -1;
275     }
276     else
277     {
278 	list.remove(ptr);
279 	return 0;
280     }
281 }
282 
operator =(const EST_TKVL<K,V> & kv)283 template<class K, class V> EST_TKVL<K, V> &EST_TKVL<K, V>::operator =
284 (const EST_TKVL<K, V> &kv)
285 {
286     list = kv.list;
287     return *this;
288 }
289 
operator +=(const EST_TKVL<K,V> & kv)290 template<class K, class V> EST_TKVL<K, V> &EST_TKVL<K, V>::operator +=
291 (const EST_TKVL<K, V> &kv)
292 {
293     list += kv.list;
294     return *this;
295 }
296 
operator +(const EST_TKVL<K,V> & kv)297 template<class K, class V> EST_TKVL<K, V> EST_TKVL<K, V>::operator + (const EST_TKVL<K, V> &kv)
298 {
299     EST_TKVL<K, V> result;
300     result = *this;
301     result += kv;
302     return result;
303 }
304 
305