4 * BabelTrace - Enumeration Type
6 * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
8 * Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
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:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
21 #include <babeltrace/compiler.h>
22 #include <babeltrace/format.h>
23 #include <babeltrace/types.h>
27 #if (__LONG_MAX__ == 2147483647L)
29 #elif (__LONG_MAX__ == 9223372036854775807L)
32 #error "Unknown long size."
36 struct definition
*_enum_definition_new(struct declaration
*declaration
,
37 struct definition_scope
*parent_scope
,
38 GQuark field_name
, int index
,
39 const char *root_name
);
41 void _enum_definition_free(struct definition
*definition
);
44 void enum_range_set_free(void *ptr
)
51 gpointer
get_uint_v(uint64_t *v
)
57 gpointer
get_int_v(int64_t *v
)
63 guint
enum_val_hash(gconstpointer key
)
65 int64_t ukey
= *(const int64_t *)key
;
67 return (guint
)ukey
^ (guint
)(ukey
>> 32);
71 gboolean
enum_val_equal(gconstpointer a
, gconstpointer b
)
73 int64_t ua
= *(const int64_t *)a
;
74 int64_t ub
= *(const int64_t *)b
;
80 void enum_val_free(void *ptr
)
84 #else /* WORD_SIZE != 32 */
86 gpointer
get_uint_v(uint64_t *v
)
92 gpointer
get_int_v(int64_t *v
)
98 guint
enum_val_hash(gconstpointer key
)
100 return g_direct_hash(key
);
104 gboolean
enum_val_equal(gconstpointer a
, gconstpointer b
)
106 return g_direct_equal(a
, b
);
110 void enum_val_free(void *ptr
)
113 #endif /* WORD_SIZE != 32 */
116 * Returns a GArray or NULL.
117 * Caller must release the GArray with g_array_unref().
119 GArray
*enum_uint_to_quark_set(const struct declaration_enum
*enum_declaration
,
122 struct enum_range_to_quark
*iter
;
123 GArray
*qs
, *ranges
= NULL
;
125 /* Single values lookup */
126 qs
= g_hash_table_lookup(enum_declaration
->table
.value_to_quark_set
,
130 bt_list_for_each_entry(iter
, &enum_declaration
->table
.range_to_quark
, node
) {
131 if (iter
->range
.start
._unsigned
> v
|| iter
->range
.end
._unsigned
< v
)
138 ranges
= g_array_sized_new(FALSE
, TRUE
,
141 g_array_set_size(ranges
, qs_len
+ 1);
143 memcpy(ranges
->data
, qs
->data
,
144 sizeof(GQuark
) * qs_len
);
145 g_array_index(ranges
, GQuark
, qs_len
) = iter
->quark
;
147 size_t qs_len
= ranges
->len
;
149 g_array_set_size(ranges
, qs_len
+ 1);
150 g_array_index(ranges
, GQuark
, qs_len
) = iter
->quark
;
163 * Returns a GArray or NULL.
164 * Caller must release the GArray with g_array_unref().
166 GArray
*enum_int_to_quark_set(const struct declaration_enum
*enum_declaration
,
169 struct enum_range_to_quark
*iter
;
170 GArray
*qs
, *ranges
= NULL
;
172 /* Single values lookup */
173 qs
= g_hash_table_lookup(enum_declaration
->table
.value_to_quark_set
,
177 bt_list_for_each_entry(iter
, &enum_declaration
->table
.range_to_quark
, node
) {
178 if (iter
->range
.start
._signed
> v
|| iter
->range
.end
._signed
< v
)
185 ranges
= g_array_sized_new(FALSE
, TRUE
,
188 g_array_set_size(ranges
, qs_len
+ 1);
190 memcpy(ranges
->data
, qs
->data
,
191 sizeof(GQuark
) * qs_len
);
192 g_array_index(ranges
, GQuark
, qs_len
) = iter
->quark
;
194 size_t qs_len
= ranges
->len
;
196 g_array_set_size(ranges
, qs_len
+ 1);
197 g_array_index(ranges
, GQuark
, qs_len
) = iter
->quark
;
210 void enum_unsigned_insert_value_to_quark_set(struct declaration_enum
*enum_declaration
,
211 uint64_t v
, GQuark q
)
216 array
= g_hash_table_lookup(enum_declaration
->table
.value_to_quark_set
,
219 array
= g_array_sized_new(FALSE
, TRUE
, sizeof(GQuark
), 1);
220 g_array_set_size(array
, 1);
221 g_array_index(array
, GQuark
, array
->len
- 1) = q
;
222 #if (WORD_SIZE == 32)
223 valuep
= g_new(uint64_t, 1);
225 #else /* WORD_SIZE != 32 */
226 valuep
= get_uint_v(&v
);
227 #endif /* WORD_SIZE != 32 */
228 g_hash_table_insert(enum_declaration
->table
.value_to_quark_set
, valuep
, array
);
230 g_array_set_size(array
, array
->len
+ 1);
231 g_array_index(array
, GQuark
, array
->len
- 1) = q
;
236 void enum_signed_insert_value_to_quark_set(struct declaration_enum
*enum_declaration
,
242 array
= g_hash_table_lookup(enum_declaration
->table
.value_to_quark_set
,
245 array
= g_array_sized_new(FALSE
, TRUE
, sizeof(GQuark
), 1);
246 g_array_set_size(array
, 1);
247 g_array_index(array
, GQuark
, array
->len
- 1) = q
;
248 #if (WORD_SIZE == 32)
249 valuep
= g_new(int64_t, 1);
251 #else /* WORD_SIZE != 32 */
252 valuep
= get_int_v(&v
);
253 #endif /* WORD_SIZE != 32 */
254 g_hash_table_insert(enum_declaration
->table
.value_to_quark_set
, valuep
, array
);
256 g_array_set_size(array
, array
->len
+ 1);
257 g_array_index(array
, GQuark
, array
->len
- 1) = q
;
261 GArray
*enum_quark_to_range_set(const struct declaration_enum
*enum_declaration
,
264 return g_hash_table_lookup(enum_declaration
->table
.quark_to_range_set
,
265 (gconstpointer
) (unsigned long) q
);
269 void enum_signed_insert_range_to_quark(struct declaration_enum
*enum_declaration
,
270 int64_t start
, int64_t end
, GQuark q
)
272 struct enum_range_to_quark
*rtoq
;
274 rtoq
= g_new(struct enum_range_to_quark
, 1);
275 bt_list_add(&rtoq
->node
, &enum_declaration
->table
.range_to_quark
);
276 rtoq
->range
.start
._signed
= start
;
277 rtoq
->range
.end
._signed
= end
;
282 void enum_unsigned_insert_range_to_quark(struct declaration_enum
*enum_declaration
,
283 uint64_t start
, uint64_t end
, GQuark q
)
285 struct enum_range_to_quark
*rtoq
;
287 rtoq
= g_new(struct enum_range_to_quark
, 1);
288 bt_list_add(&rtoq
->node
, &enum_declaration
->table
.range_to_quark
);
289 rtoq
->range
.start
._unsigned
= start
;
290 rtoq
->range
.end
._unsigned
= end
;
294 void enum_signed_insert(struct declaration_enum
*enum_declaration
,
295 int64_t start
, int64_t end
, GQuark q
)
298 struct enum_range
*range
;
301 enum_signed_insert_value_to_quark_set(enum_declaration
, start
, q
);
310 enum_signed_insert_range_to_quark(enum_declaration
, start
, end
, q
);
313 array
= g_hash_table_lookup(enum_declaration
->table
.quark_to_range_set
,
314 (gconstpointer
) (unsigned long) q
);
316 array
= g_array_sized_new(FALSE
, TRUE
,
317 sizeof(struct enum_range
), 1);
318 g_hash_table_insert(enum_declaration
->table
.quark_to_range_set
,
319 (gpointer
) (unsigned long) q
,
322 g_array_set_size(array
, array
->len
+ 1);
323 range
= &g_array_index(array
, struct enum_range
, array
->len
- 1);
324 range
->start
._signed
= start
;
325 range
->end
._signed
= end
;
328 void enum_unsigned_insert(struct declaration_enum
*enum_declaration
,
329 uint64_t start
, uint64_t end
, GQuark q
)
332 struct enum_range
*range
;
336 enum_unsigned_insert_value_to_quark_set(enum_declaration
, start
, q
);
345 enum_unsigned_insert_range_to_quark(enum_declaration
, start
, end
, q
);
348 array
= g_hash_table_lookup(enum_declaration
->table
.quark_to_range_set
,
349 (gconstpointer
) (unsigned long) q
);
351 array
= g_array_sized_new(FALSE
, TRUE
,
352 sizeof(struct enum_range
), 1);
353 g_hash_table_insert(enum_declaration
->table
.quark_to_range_set
,
354 (gpointer
) (unsigned long) q
,
357 g_array_set_size(array
, array
->len
+ 1);
358 range
= &g_array_index(array
, struct enum_range
, array
->len
- 1);
359 range
->start
._unsigned
= start
;
360 range
->end
._unsigned
= end
;
363 size_t enum_get_nr_enumerators(struct declaration_enum
*enum_declaration
)
365 return g_hash_table_size(enum_declaration
->table
.quark_to_range_set
);
369 void _enum_declaration_free(struct declaration
*declaration
)
371 struct declaration_enum
*enum_declaration
=
372 container_of(declaration
, struct declaration_enum
, p
);
373 struct enum_range_to_quark
*iter
, *tmp
;
375 g_hash_table_destroy(enum_declaration
->table
.value_to_quark_set
);
376 bt_list_for_each_entry_safe(iter
, tmp
, &enum_declaration
->table
.range_to_quark
, node
) {
377 bt_list_del(&iter
->node
);
380 g_hash_table_destroy(enum_declaration
->table
.quark_to_range_set
);
381 declaration_unref(&enum_declaration
->integer_declaration
->p
);
382 g_free(enum_declaration
);
385 struct declaration_enum
*
386 enum_declaration_new(struct declaration_integer
*integer_declaration
)
388 struct declaration_enum
*enum_declaration
;
390 enum_declaration
= g_new(struct declaration_enum
, 1);
392 enum_declaration
->table
.value_to_quark_set
= g_hash_table_new_full(enum_val_hash
,
395 enum_range_set_free
);
396 BT_INIT_LIST_HEAD(&enum_declaration
->table
.range_to_quark
);
397 enum_declaration
->table
.quark_to_range_set
= g_hash_table_new_full(g_direct_hash
,
399 NULL
, enum_range_set_free
);
400 declaration_ref(&integer_declaration
->p
);
401 enum_declaration
->integer_declaration
= integer_declaration
;
402 enum_declaration
->p
.id
= CTF_TYPE_ENUM
;
403 enum_declaration
->p
.alignment
= 1;
404 enum_declaration
->p
.declaration_free
= _enum_declaration_free
;
405 enum_declaration
->p
.definition_new
= _enum_definition_new
;
406 enum_declaration
->p
.definition_free
= _enum_definition_free
;
407 enum_declaration
->p
.ref
= 1;
408 return enum_declaration
;
413 _enum_definition_new(struct declaration
*declaration
,
414 struct definition_scope
*parent_scope
,
415 GQuark field_name
, int index
,
416 const char *root_name
)
418 struct declaration_enum
*enum_declaration
=
419 container_of(declaration
, struct declaration_enum
, p
);
420 struct definition_enum
*_enum
;
421 struct definition
*definition_integer_parent
;
424 _enum
= g_new(struct definition_enum
, 1);
425 declaration_ref(&enum_declaration
->p
);
426 _enum
->p
.declaration
= declaration
;
427 _enum
->declaration
= enum_declaration
;
430 * Use INT_MAX order to ensure that all fields of the parent
431 * scope are seen as being prior to this scope.
433 _enum
->p
.index
= root_name
? INT_MAX
: index
;
434 _enum
->p
.name
= field_name
;
435 _enum
->p
.path
= new_definition_path(parent_scope
, field_name
, root_name
);
436 _enum
->p
.scope
= new_definition_scope(parent_scope
, field_name
, root_name
);
438 ret
= register_field_definition(field_name
, &_enum
->p
,
441 definition_integer_parent
=
442 enum_declaration
->integer_declaration
->p
.definition_new(&enum_declaration
->integer_declaration
->p
,
444 g_quark_from_static_string("container"), 0, NULL
);
445 _enum
->integer
= container_of(definition_integer_parent
,
446 struct definition_integer
, p
);
451 void _enum_definition_free(struct definition
*definition
)
453 struct definition_enum
*_enum
=
454 container_of(definition
, struct definition_enum
, p
);
456 definition_unref(&_enum
->integer
->p
);
457 free_definition_scope(_enum
->p
.scope
);
458 declaration_unref(_enum
->p
.declaration
);
460 g_array_unref(_enum
->value
);