Update glib dep to 2.22 in configure.ac
[babeltrace.git] / types / enum.c
1 /*
2 * enum.c
3 *
4 * BabelTrace - Enumeration Type
5 *
6 * Copyright 2010, 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 */
18
19 #include <babeltrace/compiler.h>
20 #include <babeltrace/format.h>
21 #include <stdint.h>
22 #include <glib.h>
23
24 static
25 struct definition *_enum_definition_new(struct declaration *declaration,
26 struct definition_scope *parent_scope,
27 GQuark field_name, int index,
28 const char *root_name);
29 static
30 void _enum_definition_free(struct definition *definition);
31
32 static
33 void enum_range_set_free(void *ptr)
34 {
35 g_array_unref(ptr);
36 }
37
38 #if (__WORDSIZE == 32)
39 static inline
40 gpointer get_uint_v(uint64_t *v)
41 {
42 return v;
43 }
44
45 static inline
46 gpointer get_int_v(int64_t *v)
47 {
48 return v;
49 }
50
51 static
52 guint enum_val_hash(gconstpointer key)
53 {
54 int64_t ukey = *(const int64_t *)key;
55
56 return (guint)ukey ^ (guint)(ukey >> 32);
57 }
58
59 static
60 gboolean enum_val_equal(gconstpointer a, gconstpointer b)
61 {
62 int64_t ua = *(const int64_t *)a;
63 int64_t ub = *(const int64_t *)b;
64
65 return ua == ub;
66 }
67
68 static
69 void enum_val_free(void *ptr)
70 {
71 g_free(ptr);
72 }
73 #else /* __WORDSIZE != 32 */
74 static inline
75 gpointer get_uint_v(uint64_t *v)
76 {
77 return (gpointer) *v;
78 }
79
80 static inline
81 gpointer get_int_v(int64_t *v)
82 {
83 return (gpointer) *v;
84 }
85
86 static
87 guint enum_val_hash(gconstpointer key)
88 {
89 return g_direct_hash(key);
90 }
91
92 static
93 gboolean enum_val_equal(gconstpointer a, gconstpointer b)
94 {
95 return g_direct_equal(a, b);
96 }
97
98 static
99 void enum_val_free(void *ptr)
100 {
101 }
102 #endif /* __WORDSIZE != 32 */
103
104 /*
105 * Returns a GArray or NULL.
106 * Caller must release the GArray with g_array_unref().
107 */
108 GArray *enum_uint_to_quark_set(const struct declaration_enum *enum_declaration,
109 uint64_t v)
110 {
111 struct enum_range_to_quark *iter;
112 GArray *qs, *ranges = NULL;
113
114 /* Single values lookup */
115 qs = g_hash_table_lookup(enum_declaration->table.value_to_quark_set,
116 get_uint_v(&v));
117
118 /* Range lookup */
119 cds_list_for_each_entry(iter, &enum_declaration->table.range_to_quark, node) {
120 if (iter->range.start._unsigned > v || iter->range.end._unsigned < v)
121 continue;
122 if (!ranges) {
123 size_t qs_len = 0;
124
125 if (qs)
126 qs_len = qs->len;
127 ranges = g_array_sized_new(FALSE, TRUE,
128 sizeof(GQuark),
129 qs_len + 1);
130 g_array_set_size(ranges, qs_len + 1);
131 if (qs)
132 memcpy(ranges->data, qs->data,
133 sizeof(GQuark) * qs_len);
134 g_array_index(ranges, GQuark, qs_len) = iter->quark;
135 } else {
136 size_t qs_len = ranges->len;
137
138 g_array_set_size(ranges, qs_len + 1);
139 g_array_index(ranges, GQuark, qs_len) = iter->quark;
140 }
141 }
142 if (!ranges) {
143 if (!qs)
144 return NULL;
145 ranges = qs;
146 g_array_ref(ranges);
147 }
148 return ranges;
149 }
150
151 /*
152 * Returns a GArray or NULL.
153 * Caller must release the GArray with g_array_unref().
154 */
155 GArray *enum_int_to_quark_set(const struct declaration_enum *enum_declaration,
156 int64_t v)
157 {
158 struct enum_range_to_quark *iter;
159 GArray *qs, *ranges = NULL;
160
161 /* Single values lookup */
162 qs = g_hash_table_lookup(enum_declaration->table.value_to_quark_set,
163 get_int_v(&v));
164
165 /* Range lookup */
166 cds_list_for_each_entry(iter, &enum_declaration->table.range_to_quark, node) {
167 if (iter->range.start._signed > v || iter->range.end._signed < v)
168 continue;
169 if (!ranges) {
170 size_t qs_len = 0;
171
172 if (qs)
173 qs_len = qs->len;
174 ranges = g_array_sized_new(FALSE, TRUE,
175 sizeof(GQuark),
176 qs_len + 1);
177 g_array_set_size(ranges, qs_len + 1);
178 if (qs)
179 memcpy(ranges->data, qs->data,
180 sizeof(GQuark) * qs_len);
181 g_array_index(ranges, GQuark, qs_len) = iter->quark;
182 } else {
183 size_t qs_len = ranges->len;
184
185 g_array_set_size(ranges, qs_len + 1);
186 g_array_index(ranges, GQuark, qs_len) = iter->quark;
187 }
188 }
189 if (!ranges) {
190 if (!qs)
191 return NULL;
192 ranges = qs;
193 g_array_ref(ranges);
194 }
195 return ranges;
196 }
197
198 static
199 void enum_unsigned_insert_value_to_quark_set(struct declaration_enum *enum_declaration,
200 uint64_t v, GQuark q)
201 {
202 uint64_t *valuep;
203 GArray *array;
204
205 array = g_hash_table_lookup(enum_declaration->table.value_to_quark_set,
206 get_uint_v(&v));
207 if (!array) {
208 array = g_array_sized_new(FALSE, TRUE, sizeof(GQuark), 1);
209 g_array_set_size(array, 1);
210 g_array_index(array, GQuark, array->len - 1) = q;
211 #if (__WORDSIZE == 32)
212 valuep = g_new(uint64_t, 1);
213 *valuep = v;
214 #else /* __WORDSIZE != 32 */
215 valuep = get_uint_v(&v);
216 #endif /* __WORDSIZE != 32 */
217 g_hash_table_insert(enum_declaration->table.value_to_quark_set, valuep, array);
218 } else {
219 g_array_set_size(array, array->len + 1);
220 g_array_index(array, GQuark, array->len - 1) = q;
221 }
222 }
223
224 static
225 void enum_signed_insert_value_to_quark_set(struct declaration_enum *enum_declaration,
226 int64_t v, GQuark q)
227 {
228 int64_t *valuep;
229 GArray *array;
230
231 array = g_hash_table_lookup(enum_declaration->table.value_to_quark_set,
232 get_int_v(&v));
233 if (!array) {
234 array = g_array_sized_new(FALSE, TRUE, sizeof(GQuark), 1);
235 g_array_set_size(array, 1);
236 g_array_index(array, GQuark, array->len - 1) = q;
237 #if (__WORDSIZE == 32)
238 valuep = g_new(int64_t, 1);
239 *valuep = v;
240 #else /* __WORDSIZE != 32 */
241 valuep = get_int_v(&v);
242 #endif /* __WORDSIZE != 32 */
243 g_hash_table_insert(enum_declaration->table.value_to_quark_set, valuep, array);
244 } else {
245 g_array_set_size(array, array->len + 1);
246 g_array_index(array, GQuark, array->len - 1) = q;
247 }
248 }
249
250 GArray *enum_quark_to_range_set(const struct declaration_enum *enum_declaration,
251 GQuark q)
252 {
253 return g_hash_table_lookup(enum_declaration->table.quark_to_range_set,
254 (gconstpointer) (unsigned long) q);
255 }
256
257 static
258 void enum_signed_insert_range_to_quark(struct declaration_enum *enum_declaration,
259 int64_t start, int64_t end, GQuark q)
260 {
261 struct enum_range_to_quark *rtoq;
262
263 rtoq = g_new(struct enum_range_to_quark, 1);
264 cds_list_add(&rtoq->node, &enum_declaration->table.range_to_quark);
265 rtoq->range.start._signed = start;
266 rtoq->range.end._signed = end;
267 rtoq->quark = q;
268 }
269
270 static
271 void enum_unsigned_insert_range_to_quark(struct declaration_enum *enum_declaration,
272 uint64_t start, uint64_t end, GQuark q)
273 {
274 struct enum_range_to_quark *rtoq;
275
276 rtoq = g_new(struct enum_range_to_quark, 1);
277 cds_list_add(&rtoq->node, &enum_declaration->table.range_to_quark);
278 rtoq->range.start._unsigned = start;
279 rtoq->range.end._unsigned = end;
280 rtoq->quark = q;
281 }
282
283 void enum_signed_insert(struct declaration_enum *enum_declaration,
284 int64_t start, int64_t end, GQuark q)
285 {
286 GArray *array;
287 struct enum_range *range;
288
289 if (start == end) {
290 enum_signed_insert_value_to_quark_set(enum_declaration, start, q);
291 } else {
292 if (start > end) {
293 uint64_t tmp;
294
295 tmp = start;
296 start = end;
297 end = tmp;
298 }
299 enum_signed_insert_range_to_quark(enum_declaration, start, end, q);
300 }
301
302 array = g_hash_table_lookup(enum_declaration->table.quark_to_range_set,
303 (gconstpointer) (unsigned long) q);
304 if (!array) {
305 array = g_array_sized_new(FALSE, TRUE,
306 sizeof(struct enum_range), 1);
307 g_hash_table_insert(enum_declaration->table.quark_to_range_set,
308 (gpointer) (unsigned long) q,
309 array);
310 }
311 g_array_set_size(array, array->len + 1);
312 range = &g_array_index(array, struct enum_range, array->len - 1);
313 range->start._signed = start;
314 range->end._signed = end;
315 }
316
317 void enum_unsigned_insert(struct declaration_enum *enum_declaration,
318 uint64_t start, uint64_t end, GQuark q)
319 {
320 GArray *array;
321 struct enum_range *range;
322
323
324 if (start == end) {
325 enum_unsigned_insert_value_to_quark_set(enum_declaration, start, q);
326 } else {
327 if (start > end) {
328 uint64_t tmp;
329
330 tmp = start;
331 start = end;
332 end = tmp;
333 }
334 enum_unsigned_insert_range_to_quark(enum_declaration, start, end, q);
335 }
336
337 array = g_hash_table_lookup(enum_declaration->table.quark_to_range_set,
338 (gconstpointer) (unsigned long) q);
339 if (!array) {
340 array = g_array_sized_new(FALSE, TRUE,
341 sizeof(struct enum_range), 1);
342 g_hash_table_insert(enum_declaration->table.quark_to_range_set,
343 (gpointer) (unsigned long) q,
344 array);
345 }
346 g_array_set_size(array, array->len + 1);
347 range = &g_array_index(array, struct enum_range, array->len - 1);
348 range->start._unsigned = start;
349 range->end._unsigned = end;
350 }
351
352 size_t enum_get_nr_enumerators(struct declaration_enum *enum_declaration)
353 {
354 return g_hash_table_size(enum_declaration->table.quark_to_range_set);
355 }
356
357 static
358 void _enum_declaration_free(struct declaration *declaration)
359 {
360 struct declaration_enum *enum_declaration =
361 container_of(declaration, struct declaration_enum, p);
362 struct enum_range_to_quark *iter, *tmp;
363
364 g_hash_table_destroy(enum_declaration->table.value_to_quark_set);
365 cds_list_for_each_entry_safe(iter, tmp, &enum_declaration->table.range_to_quark, node) {
366 cds_list_del(&iter->node);
367 g_free(iter);
368 }
369 g_hash_table_destroy(enum_declaration->table.quark_to_range_set);
370 declaration_unref(&enum_declaration->integer_declaration->p);
371 g_free(enum_declaration);
372 }
373
374 struct declaration_enum *
375 enum_declaration_new(struct declaration_integer *integer_declaration)
376 {
377 struct declaration_enum *enum_declaration;
378
379 enum_declaration = g_new(struct declaration_enum, 1);
380
381 enum_declaration->table.value_to_quark_set = g_hash_table_new_full(enum_val_hash,
382 enum_val_equal,
383 enum_val_free,
384 enum_range_set_free);
385 CDS_INIT_LIST_HEAD(&enum_declaration->table.range_to_quark);
386 enum_declaration->table.quark_to_range_set = g_hash_table_new_full(g_direct_hash,
387 g_direct_equal,
388 NULL, enum_range_set_free);
389 declaration_ref(&integer_declaration->p);
390 enum_declaration->integer_declaration = integer_declaration;
391 enum_declaration->p.id = CTF_TYPE_ENUM;
392 enum_declaration->p.alignment = 1;
393 enum_declaration->p.declaration_free = _enum_declaration_free;
394 enum_declaration->p.definition_new = _enum_definition_new;
395 enum_declaration->p.definition_free = _enum_definition_free;
396 enum_declaration->p.ref = 1;
397 return enum_declaration;
398 }
399
400 static
401 struct definition *
402 _enum_definition_new(struct declaration *declaration,
403 struct definition_scope *parent_scope,
404 GQuark field_name, int index,
405 const char *root_name)
406 {
407 struct declaration_enum *enum_declaration =
408 container_of(declaration, struct declaration_enum, p);
409 struct definition_enum *_enum;
410 struct definition *definition_integer_parent;
411 int ret;
412
413 _enum = g_new(struct definition_enum, 1);
414 declaration_ref(&enum_declaration->p);
415 _enum->p.declaration = declaration;
416 _enum->declaration = enum_declaration;
417 _enum->p.ref = 1;
418 /*
419 * Use INT_MAX order to ensure that all fields of the parent
420 * scope are seen as being prior to this scope.
421 */
422 _enum->p.index = root_name ? INT_MAX : index;
423 _enum->p.name = field_name;
424 _enum->p.path = new_definition_path(parent_scope, field_name, root_name);
425 _enum->p.scope = new_definition_scope(parent_scope, field_name, root_name);
426 _enum->value = NULL;
427 ret = register_field_definition(field_name, &_enum->p,
428 parent_scope);
429 assert(!ret);
430 definition_integer_parent =
431 enum_declaration->integer_declaration->p.definition_new(&enum_declaration->integer_declaration->p,
432 _enum->p.scope,
433 g_quark_from_static_string("container"), 0, NULL);
434 _enum->integer = container_of(definition_integer_parent,
435 struct definition_integer, p);
436 return &_enum->p;
437 }
438
439 static
440 void _enum_definition_free(struct definition *definition)
441 {
442 struct definition_enum *_enum =
443 container_of(definition, struct definition_enum, p);
444
445 definition_unref(&_enum->integer->p);
446 free_definition_scope(_enum->p.scope);
447 declaration_unref(_enum->p.declaration);
448 if (_enum->value)
449 g_array_unref(_enum->value);
450 g_free(_enum);
451 }
This page took 0.039912 seconds and 4 git commands to generate.