4 * BabelTrace - Enumeration Type
6 * Copyright 2010, 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
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:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
19 #include <babeltrace/compiler.h>
20 #include <babeltrace/format.h>
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
);
30 void _enum_definition_free(struct definition
*definition
);
33 void enum_range_set_free(void *ptr
)
38 #if (__WORDSIZE == 32)
40 gpointer
get_uint_v(uint64_t *v
)
46 gpointer
get_int_v(int64_t *v
)
52 guint
enum_val_hash(gconstpointer key
)
54 int64_t ukey
= *(const int64_t *)key
;
56 return (guint
)ukey
^ (guint
)(ukey
>> 32);
60 gboolean
enum_val_equal(gconstpointer a
, gconstpointer b
)
62 int64_t ua
= *(const int64_t *)a
;
63 int64_t ub
= *(const int64_t *)b
;
69 void enum_val_free(void *ptr
)
73 #else /* __WORDSIZE != 32 */
75 gpointer
get_uint_v(uint64_t *v
)
81 gpointer
get_int_v(int64_t *v
)
87 guint
enum_val_hash(gconstpointer key
)
89 return g_direct_hash(key
);
93 gboolean
enum_val_equal(gconstpointer a
, gconstpointer b
)
95 return g_direct_equal(a
, b
);
99 void enum_val_free(void *ptr
)
102 #endif /* __WORDSIZE != 32 */
105 * Returns a GArray or NULL.
106 * Caller must release the GArray with g_array_unref().
108 GArray
*enum_uint_to_quark_set(const struct declaration_enum
*enum_declaration
,
111 struct enum_range_to_quark
*iter
;
112 GArray
*qs
, *ranges
= NULL
;
114 /* Single values lookup */
115 qs
= g_hash_table_lookup(enum_declaration
->table
.value_to_quark_set
,
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
)
127 ranges
= g_array_sized_new(FALSE
, TRUE
,
130 g_array_set_size(ranges
, qs_len
+ 1);
132 memcpy(ranges
->data
, qs
->data
,
133 sizeof(GQuark
) * qs_len
);
134 g_array_index(ranges
, GQuark
, qs_len
) = iter
->quark
;
136 size_t qs_len
= ranges
->len
;
138 g_array_set_size(ranges
, qs_len
+ 1);
139 g_array_index(ranges
, GQuark
, qs_len
) = iter
->quark
;
152 * Returns a GArray or NULL.
153 * Caller must release the GArray with g_array_unref().
155 GArray
*enum_int_to_quark_set(const struct declaration_enum
*enum_declaration
,
158 struct enum_range_to_quark
*iter
;
159 GArray
*qs
, *ranges
= NULL
;
161 /* Single values lookup */
162 qs
= g_hash_table_lookup(enum_declaration
->table
.value_to_quark_set
,
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
)
174 ranges
= g_array_sized_new(FALSE
, TRUE
,
177 g_array_set_size(ranges
, qs_len
+ 1);
179 memcpy(ranges
->data
, qs
->data
,
180 sizeof(GQuark
) * qs_len
);
181 g_array_index(ranges
, GQuark
, qs_len
) = iter
->quark
;
183 size_t qs_len
= ranges
->len
;
185 g_array_set_size(ranges
, qs_len
+ 1);
186 g_array_index(ranges
, GQuark
, qs_len
) = iter
->quark
;
199 void enum_unsigned_insert_value_to_quark_set(struct declaration_enum
*enum_declaration
,
200 uint64_t v
, GQuark q
)
205 array
= g_hash_table_lookup(enum_declaration
->table
.value_to_quark_set
,
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);
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
);
219 g_array_set_size(array
, array
->len
+ 1);
220 g_array_index(array
, GQuark
, array
->len
- 1) = q
;
225 void enum_signed_insert_value_to_quark_set(struct declaration_enum
*enum_declaration
,
231 array
= g_hash_table_lookup(enum_declaration
->table
.value_to_quark_set
,
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);
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
);
245 g_array_set_size(array
, array
->len
+ 1);
246 g_array_index(array
, GQuark
, array
->len
- 1) = q
;
250 GArray
*enum_quark_to_range_set(const struct declaration_enum
*enum_declaration
,
253 return g_hash_table_lookup(enum_declaration
->table
.quark_to_range_set
,
254 (gconstpointer
) (unsigned long) q
);
258 void enum_signed_insert_range_to_quark(struct declaration_enum
*enum_declaration
,
259 int64_t start
, int64_t end
, GQuark q
)
261 struct enum_range_to_quark
*rtoq
;
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
;
271 void enum_unsigned_insert_range_to_quark(struct declaration_enum
*enum_declaration
,
272 uint64_t start
, uint64_t end
, GQuark q
)
274 struct enum_range_to_quark
*rtoq
;
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
;
283 void enum_signed_insert(struct declaration_enum
*enum_declaration
,
284 int64_t start
, int64_t end
, GQuark q
)
287 struct enum_range
*range
;
290 enum_signed_insert_value_to_quark_set(enum_declaration
, start
, q
);
299 enum_signed_insert_range_to_quark(enum_declaration
, start
, end
, q
);
302 array
= g_hash_table_lookup(enum_declaration
->table
.quark_to_range_set
,
303 (gconstpointer
) (unsigned long) q
);
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
,
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
;
317 void enum_unsigned_insert(struct declaration_enum
*enum_declaration
,
318 uint64_t start
, uint64_t end
, GQuark q
)
321 struct enum_range
*range
;
325 enum_unsigned_insert_value_to_quark_set(enum_declaration
, start
, q
);
334 enum_unsigned_insert_range_to_quark(enum_declaration
, start
, end
, q
);
337 array
= g_hash_table_lookup(enum_declaration
->table
.quark_to_range_set
,
338 (gconstpointer
) (unsigned long) q
);
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
,
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
;
352 size_t enum_get_nr_enumerators(struct declaration_enum
*enum_declaration
)
354 return g_hash_table_size(enum_declaration
->table
.quark_to_range_set
);
358 void _enum_declaration_free(struct declaration
*declaration
)
360 struct declaration_enum
*enum_declaration
=
361 container_of(declaration
, struct declaration_enum
, p
);
362 struct enum_range_to_quark
*iter
, *tmp
;
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
);
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
);
374 struct declaration_enum
*
375 enum_declaration_new(struct declaration_integer
*integer_declaration
)
377 struct declaration_enum
*enum_declaration
;
379 enum_declaration
= g_new(struct declaration_enum
, 1);
381 enum_declaration
->table
.value_to_quark_set
= g_hash_table_new_full(enum_val_hash
,
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
,
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
;
402 _enum_definition_new(struct declaration
*declaration
,
403 struct definition_scope
*parent_scope
,
404 GQuark field_name
, int index
,
405 const char *root_name
)
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
;
413 _enum
= g_new(struct definition_enum
, 1);
414 declaration_ref(&enum_declaration
->p
);
415 _enum
->p
.declaration
= declaration
;
416 _enum
->declaration
= enum_declaration
;
419 * Use INT_MAX order to ensure that all fields of the parent
420 * scope are seen as being prior to this scope.
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
);
427 ret
= register_field_definition(field_name
, &_enum
->p
,
430 definition_integer_parent
=
431 enum_declaration
->integer_declaration
->p
.definition_new(&enum_declaration
->integer_declaration
->p
,
433 g_quark_from_static_string("container"), 0, NULL
);
434 _enum
->integer
= container_of(definition_integer_parent
,
435 struct definition_integer
, p
);
440 void _enum_definition_free(struct definition
*definition
)
442 struct definition_enum
*_enum
=
443 container_of(definition
, struct definition_enum
, p
);
445 definition_unref(&_enum
->integer
->p
);
446 free_definition_scope(_enum
->p
.scope
);
447 declaration_unref(_enum
->p
.declaration
);
449 g_array_unref(_enum
->value
);