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