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