- improve set transformation
[libfirm] / ir / ident / ident.c
1 /*
2  * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief     Hash table to store names.
23  * @author    Goetz Lindenmaier
24  * @version   $Id$
25  */
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <assert.h>
31 #include <ctype.h>
32 #include <string.h>
33 #include <stddef.h>
34 #include <stdlib.h>
35
36 #ifdef FIRM_ENABLE_WCHAR
37 #include <wchar.h>
38 #endif
39
40 #include "ident_t.h"
41 #include "set.h"
42 #include "xmalloc.h"
43
44 /* for debugging only, not the real implementation */
45 struct _ident {
46   char reserved[sizeof(unsigned) + sizeof(size_t)];
47   char data[1];
48 };
49
50 /** The current ident module implementation. */
51 static ident_if_t impl;
52
53 /**
54  * Stores a string in the ident module and returns a handle for the string.
55  *
56  * @param handle   the handle for the set
57  * @param str      the string which shall be stored
58  * @param len      length of str in bytes
59  *
60  * @return id - a handle for the generated ident
61  *
62  * Default implementation using libfirm sets.
63  */
64 static ident *set_new_id_from_chars(void *handle, const char *str, int len)
65 {
66   set *id_set = handle;
67
68   /* GL: Who added this assert?  And why? */
69   //assert(len > 0);
70   return (ident *)set_hinsert0(id_set, str, len, ID_HASH(unsigned char, str, len));
71 }
72
73 /**
74  * Stores a string in the ident module and returns a handle for the string.
75  *
76  * @param handle   the handle for the set
77  * @param str      the string (or whatever) which shall be stored
78  *
79  * Default implementation using libfirm sets.
80  */
81 static ident *set_new_id_from_str(void *handle, const char *str)
82 {
83   assert(str);
84   return (ident *)set_new_id_from_chars(handle, str, strlen(str));
85 }
86
87 /**
88  * Returns a string represented by an ident.
89  *
90  * @param handle   the handle for the set
91  * @param id       the ident
92  *
93  * Default implementation using libfirm sets.
94  */
95 static const char *set_get_id_str(void *handle, ident *id)
96 {
97   struct set_entry *entry = (struct set_entry *)id;
98   (void) handle;
99
100   return (const char *)entry->dptr;
101 }
102
103 /**
104  * Returns the length of the string represented by an ident.
105  *
106  * @param handle   the handle for the set
107  * @param id       the ident
108  *
109  * Default implementation using libfirm sets.
110  */
111 static int set_get_id_strlen(void *handle, ident *id)
112 {
113   struct set_entry *entry = (struct set_entry *)id;
114   (void) handle;
115
116   return entry->size;
117 }
118
119 /**
120  * Default implementation using libfirm sets.
121  */
122 void set_finish_ident(void *handle) {
123   set *id_set = handle;
124
125   del_set(id_set);
126 }
127
128 /**
129  * Default implementation if no new_id_from_str() is provided.
130  */
131 static ident *def_new_id_from_str(void *handle, const char *str)
132 {
133   return impl.new_id_from_chars(handle, str, strlen(str));
134 }
135
136 /**
137  * Default implementation if no get_id_strlen() is provided.
138  */
139 static int def_get_id_strlen(void *handle, ident *id)
140 {
141   return strlen(impl.get_id_str(handle, id));
142 }
143
144 #ifdef FIRM_ENABLE_WCHAR
145 /**
146  * Stores a wide character string in the ident module and returns a
147  * handle for the string.
148  *
149  * @param handle   the handle for the set
150  * @param wstr     the wide character string which shall be stored
151  * @param len      length of wstr
152  *
153  * @return id - a handle for the generated ident
154  *
155  * Default implementation using libfirm sets.
156  */
157 static ident *set_new_id_from_wchars(void *handle, const wchar_t *wstr, int len)
158 {
159   set *id_set = handle;
160   wchar_t *tmp;
161
162   /* can't use hinsert0 here, so copy and add a 0 */
163   tmp = alloca((len + 1) * sizeof(*tmp));
164   memcpy(tmp, wstr, len * sizeof(*tmp));
165   tmp[len] = L'\0';
166
167   return (ident *)set_hinsert(id_set, tmp, (len + 1) * sizeof(wchar_t), ID_HASH(wchar_t, tmp, len));
168 }
169
170 /**
171  * Stores a wide character string in the ident module and
172  * returns a handle for the string.
173  *
174  * @param handle   the handle for the set
175  * @param wstr     the wide character string which shall be stored
176  *
177  * Default implementation using libfirm sets.
178  */
179 static ident *set_new_id_from_wcs(void *handle, const wchar_t *wstr)
180 {
181   assert(wstr);
182   return (ident *)set_new_id_from_wchars(handle, wstr, wcslen(wstr));
183 }
184
185 /**
186  * Returns a wide character string represented by an ident.
187  *
188  * @param handle   the handle for the set
189  * @param id       the ident
190  *
191  * Default implementation using libfirm sets.
192  */
193 static const wchar_t *set_get_id_wcs(void *handle, ident *id)
194 {
195   struct set_entry *entry = (struct set_entry *)id;
196
197   return (const wchar_t *)entry->dptr;
198 }
199
200 /**
201  * Returns the length of the string represented by an ident.
202  *
203  * @param handle   the handle for the set
204  * @param id       the ident
205  *
206  * Default implementation using libfirm sets.
207  */
208 static int set_get_id_wcslen(void *handle, ident *id)
209 {
210   struct set_entry *entry = (struct set_entry *)id;
211
212   /* len + \0 is stored for wchar_t */
213   return entry->size / sizeof(wchar_t) - 1;
214 }
215
216 /**
217  * Default implementation if no new_id_from_wcs() is provided.
218  */
219 static ident *def_new_id_from_wcs(void *handle, const wchar_t *wstr)
220 {
221   return impl.new_id_from_wchars(handle, wstr, wcslen(wstr));
222 }
223
224 /**
225  * Default implementation if no new_id_from_wchars() is provided.
226  */
227 static ident *def_new_id_from_wchars(void *handle, const wchar_t *wstr, int len)
228 {
229   return impl.new_id_from_chars(handle, (const char *)wstr, (len + 1) * sizeof(wchar_t));
230 }
231
232 /**
233  * Default implementation if no get_id_wcs() is provided.
234  */
235 static const wchar_t *def_get_id_wcs(void *handle, ident *id)
236 {
237   return (const wchar_t *)impl.get_id_str(handle, id);
238 }
239
240 /**
241  * Default implementation if no get_id_wcslen() is provided.
242  */
243 static int def_get_id_wcslen(void *handle, ident *id)
244 {
245   return wcslen(impl.get_id_wcs(handle, id));
246 }
247 #endif /* FIRM_ENABLE_WCHAR */
248
249 /* Initialize the ident module. */
250 void init_ident(ident_if_t *id_if, int initial_n_idents)
251 {
252   if (id_if) {
253     memcpy(&impl, id_if, sizeof(impl));
254
255     if (! impl.new_id_from_str)
256       impl.new_id_from_str = def_new_id_from_str;
257     if (! impl.get_id_strlen)
258       impl.get_id_strlen = def_get_id_strlen;
259
260 #ifdef FIRM_ENABLE_WCHAR
261     if (! impl.new_id_from_wcs)
262       impl.new_id_from_wcs = def_new_id_from_wcs;
263     if (! impl.new_id_from_wchars)
264       impl.new_id_from_wchars = def_new_id_from_wchars;
265     if (! impl.get_id_wcs)
266       impl.get_id_wcs = def_get_id_wcs;
267     if (! impl.get_id_wcslen)
268       impl.get_id_wcslen = def_get_id_wcslen;
269 #endif /* FIRM_ENABLE_WCHAR */
270   }
271   else {
272    impl.new_id_from_str    = set_new_id_from_str;
273    impl.new_id_from_chars  = set_new_id_from_chars;
274    impl.get_id_str         = set_get_id_str;
275    impl.get_id_strlen      = set_get_id_strlen;
276    impl.finish_ident       = set_finish_ident;
277 #ifdef FIRM_ENABLE_WCHAR
278    impl.new_id_from_wcs    = set_new_id_from_wcs;
279    impl.new_id_from_wchars = set_new_id_from_wchars;
280    impl.get_id_wcs         = set_get_id_wcs;
281    impl.get_id_wcslen      = set_get_id_wcslen;
282 #endif /* FIRM_ENABLE_WCHAR */
283
284    impl.handle = new_set(memcmp, initial_n_idents);
285   }
286 }
287
288 ident *new_id_from_str(const char *str)
289 {
290   assert(str);
291   return impl.new_id_from_str(impl.handle, str);
292 }
293
294 ident *new_id_from_chars(const char *str, int len)
295 {
296   assert(len > 0);
297   return impl.new_id_from_chars(impl.handle, str, len);
298 }
299
300 const char *get_id_str(ident *id)
301 {
302   return impl.get_id_str(impl.handle, id);
303 }
304
305 int get_id_strlen(ident *id)
306 {
307   return impl.get_id_strlen(impl.handle, id);
308 }
309
310 void finish_ident(void) {
311   if (impl.finish_ident)
312     impl.finish_ident(impl.handle);
313 }
314
315 int id_is_prefix(ident *prefix, ident *id)
316 {
317   if (get_id_strlen(prefix) > get_id_strlen(id)) return 0;
318   return 0 == memcmp(get_id_str(prefix), get_id_str(id), get_id_strlen(prefix));
319 }
320
321 int id_is_suffix(ident *suffix, ident *id)
322 {
323   int suflen = get_id_strlen(suffix);
324   int idlen  = get_id_strlen(id);
325   const char *part;
326
327   if (suflen > idlen) return 0;
328
329   part = get_id_str(id);
330   part = part + (idlen - suflen);
331
332   return 0 == memcmp(get_id_str(suffix), part, suflen);
333 }
334
335 int id_contains_char(ident *id, char c)
336 {
337   return strchr(get_id_str(id), c) != NULL;
338 }
339
340 #ifdef FIRM_ENABLE_WCHAR
341
342 ident *new_id_from_wcs (const wchar_t *str)
343 {
344   assert(str);
345   return impl.new_id_from_wcs(impl.handle, str);
346 }
347
348 ident *new_id_from_wchars (const wchar_t *str, int len)
349 {
350   assert(len > 0);
351   return impl.new_id_from_wchars(impl.handle, str, len);
352 }
353
354 const wchar_t *get_id_wcs(ident *id)
355 {
356   return impl.get_id_wcs(impl.handle, id);
357 }
358
359 int  get_id_wcslen(ident *id)
360 {
361   return impl.get_id_wcslen(impl.handle, id);
362 }
363
364 int id_contains_wchar (ident *id, wchar_t c)
365 {
366   return wcschr(get_id_wcs(id), c) != NULL;
367 }
368
369 #endif /* FIRM_ENABLE_WCHAR */