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.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 #include <babeltrace/compiler.h>
30 #include <babeltrace/format.h>
31 #include <babeltrace/types.h>
35 #if (__LONG_MAX__ == 2147483647L)
37 #elif (__LONG_MAX__ == 9223372036854775807L)
40 #error "Unknown long size."
44 struct bt_definition
*_enum_definition_new(struct bt_declaration
*declaration
,
45 struct definition_scope
*parent_scope
,
46 GQuark field_name
, int index
,
47 const char *root_name
);
49 void _enum_definition_free(struct bt_definition
*definition
);
52 void enum_range_set_free(void *ptr
)
59 gpointer
get_uint_v(uint64_t *v
)
65 gpointer
get_int_v(int64_t *v
)
71 guint
enum_val_hash(gconstpointer key
)
73 int64_t ukey
= *(const int64_t *)key
;
75 return (guint
)ukey
^ (guint
)(ukey
>> 32);
79 gboolean
enum_val_equal(gconstpointer a
, gconstpointer b
)
81 int64_t ua
= *(const int64_t *)a
;
82 int64_t ub
= *(const int64_t *)b
;
88 void enum_val_free(void *ptr
)
92 #else /* WORD_SIZE != 32 */
94 gpointer
get_uint_v(uint64_t *v
)
100 gpointer
get_int_v(int64_t *v
)
102 return (gpointer
) *v
;
106 guint
enum_val_hash(gconstpointer key
)
108 return g_direct_hash(key
);
112 gboolean
enum_val_equal(gconstpointer a
, gconstpointer b
)
114 return g_direct_equal(a
, b
);
118 void enum_val_free(void *ptr
)
121 #endif /* WORD_SIZE != 32 */
124 * Returns a GArray or NULL.
125 * Caller must release the GArray with g_array_unref().
127 GArray
*bt_enum_uint_to_quark_set(const struct declaration_enum
*enum_declaration
,
130 struct enum_range_to_quark
*iter
;
131 GArray
*qs
, *ranges
= NULL
;
133 /* Single values lookup */
134 qs
= g_hash_table_lookup(enum_declaration
->table
.value_to_quark_set
,
138 bt_list_for_each_entry(iter
, &enum_declaration
->table
.range_to_quark
, node
) {
139 if (iter
->range
.start
._unsigned
> v
|| iter
->range
.end
._unsigned
< v
)
146 ranges
= g_array_sized_new(FALSE
, TRUE
,
149 g_array_set_size(ranges
, qs_len
+ 1);
151 memcpy(ranges
->data
, qs
->data
,
152 sizeof(GQuark
) * qs_len
);
153 g_array_index(ranges
, GQuark
, qs_len
) = iter
->quark
;
155 size_t qs_len
= ranges
->len
;
157 g_array_set_size(ranges
, qs_len
+ 1);
158 g_array_index(ranges
, GQuark
, qs_len
) = iter
->quark
;
171 * Returns a GArray or NULL.
172 * Caller must release the GArray with g_array_unref().
174 GArray
*bt_enum_int_to_quark_set(const struct declaration_enum
*enum_declaration
,
177 struct enum_range_to_quark
*iter
;
178 GArray
*qs
, *ranges
= NULL
;
180 /* Single values lookup */
181 qs
= g_hash_table_lookup(enum_declaration
->table
.value_to_quark_set
,
185 bt_list_for_each_entry(iter
, &enum_declaration
->table
.range_to_quark
, node
) {
186 if (iter
->range
.start
._signed
> v
|| iter
->range
.end
._signed
< v
)
193 ranges
= g_array_sized_new(FALSE
, TRUE
,
196 g_array_set_size(ranges
, qs_len
+ 1);
198 memcpy(ranges
->data
, qs
->data
,
199 sizeof(GQuark
) * qs_len
);
200 g_array_index(ranges
, GQuark
, qs_len
) = iter
->quark
;
202 size_t qs_len
= ranges
->len
;
204 g_array_set_size(ranges
, qs_len
+ 1);
205 g_array_index(ranges
, GQuark
, qs_len
) = iter
->quark
;
218 void bt_enum_unsigned_insert_value_to_quark_set(struct declaration_enum
*enum_declaration
,
219 uint64_t v
, GQuark q
)
224 array
= g_hash_table_lookup(enum_declaration
->table
.value_to_quark_set
,
227 array
= g_array_sized_new(FALSE
, TRUE
, sizeof(GQuark
), 1);
228 g_array_set_size(array
, 1);
229 g_array_index(array
, GQuark
, array
->len
- 1) = q
;
230 #if (WORD_SIZE == 32)
231 valuep
= g_new(uint64_t, 1);
233 #else /* WORD_SIZE != 32 */
234 valuep
= get_uint_v(&v
);
235 #endif /* WORD_SIZE != 32 */
236 g_hash_table_insert(enum_declaration
->table
.value_to_quark_set
, valuep
, array
);
238 g_array_set_size(array
, array
->len
+ 1);
239 g_array_index(array
, GQuark
, array
->len
- 1) = q
;
244 void bt_enum_signed_insert_value_to_quark_set(struct declaration_enum
*enum_declaration
,
250 array
= g_hash_table_lookup(enum_declaration
->table
.value_to_quark_set
,
253 array
= g_array_sized_new(FALSE
, TRUE
, sizeof(GQuark
), 1);
254 g_array_set_size(array
, 1);
255 g_array_index(array
, GQuark
, array
->len
- 1) = q
;
256 #if (WORD_SIZE == 32)
257 valuep
= g_new(int64_t, 1);
259 #else /* WORD_SIZE != 32 */
260 valuep
= get_int_v(&v
);
261 #endif /* WORD_SIZE != 32 */
262 g_hash_table_insert(enum_declaration
->table
.value_to_quark_set
, valuep
, array
);
264 g_array_set_size(array
, array
->len
+ 1);
265 g_array_index(array
, GQuark
, array
->len
- 1) = q
;
269 GArray
*bt_enum_quark_to_range_set(const struct declaration_enum
*enum_declaration
,
272 return g_hash_table_lookup(enum_declaration
->table
.quark_to_range_set
,
273 (gconstpointer
) GUINT_TO_POINTER(q
));
277 void bt_enum_signed_insert_range_to_quark(struct declaration_enum
*enum_declaration
,
278 int64_t start
, int64_t end
, GQuark q
)
280 struct enum_range_to_quark
*rtoq
;
282 rtoq
= g_new(struct enum_range_to_quark
, 1);
283 bt_list_add(&rtoq
->node
, &enum_declaration
->table
.range_to_quark
);
284 rtoq
->range
.start
._signed
= start
;
285 rtoq
->range
.end
._signed
= end
;
290 void bt_enum_unsigned_insert_range_to_quark(struct declaration_enum
*enum_declaration
,
291 uint64_t start
, uint64_t end
, GQuark q
)
293 struct enum_range_to_quark
*rtoq
;
295 rtoq
= g_new(struct enum_range_to_quark
, 1);
296 bt_list_add(&rtoq
->node
, &enum_declaration
->table
.range_to_quark
);
297 rtoq
->range
.start
._unsigned
= start
;
298 rtoq
->range
.end
._unsigned
= end
;
302 void bt_enum_signed_insert(struct declaration_enum
*enum_declaration
,
303 int64_t start
, int64_t end
, GQuark q
)
306 struct enum_range
*range
;
309 bt_enum_signed_insert_value_to_quark_set(enum_declaration
, start
, q
);
318 bt_enum_signed_insert_range_to_quark(enum_declaration
, start
, end
, q
);
321 array
= g_hash_table_lookup(enum_declaration
->table
.quark_to_range_set
,
322 (gconstpointer
) GUINT_TO_POINTER(q
));
324 array
= g_array_sized_new(FALSE
, TRUE
,
325 sizeof(struct enum_range
), 1);
326 g_hash_table_insert(enum_declaration
->table
.quark_to_range_set
,
330 g_array_set_size(array
, array
->len
+ 1);
331 range
= &g_array_index(array
, struct enum_range
, array
->len
- 1);
332 range
->start
._signed
= start
;
333 range
->end
._signed
= end
;
336 void bt_enum_unsigned_insert(struct declaration_enum
*enum_declaration
,
337 uint64_t start
, uint64_t end
, GQuark q
)
340 struct enum_range
*range
;
344 bt_enum_unsigned_insert_value_to_quark_set(enum_declaration
, start
, q
);
353 bt_enum_unsigned_insert_range_to_quark(enum_declaration
, start
, end
, q
);
356 array
= g_hash_table_lookup(enum_declaration
->table
.quark_to_range_set
,
357 (gconstpointer
) GUINT_TO_POINTER(q
));
359 array
= g_array_sized_new(FALSE
, TRUE
,
360 sizeof(struct enum_range
), 1);
361 g_hash_table_insert(enum_declaration
->table
.quark_to_range_set
,
365 g_array_set_size(array
, array
->len
+ 1);
366 range
= &g_array_index(array
, struct enum_range
, array
->len
- 1);
367 range
->start
._unsigned
= start
;
368 range
->end
._unsigned
= end
;
371 size_t bt_enum_get_nr_enumerators(struct declaration_enum
*enum_declaration
)
373 return g_hash_table_size(enum_declaration
->table
.quark_to_range_set
);
377 void _enum_declaration_free(struct bt_declaration
*declaration
)
379 struct declaration_enum
*enum_declaration
=
380 container_of(declaration
, struct declaration_enum
, p
);
381 struct enum_range_to_quark
*iter
, *tmp
;
383 g_hash_table_destroy(enum_declaration
->table
.value_to_quark_set
);
384 bt_list_for_each_entry_safe(iter
, tmp
, &enum_declaration
->table
.range_to_quark
, node
) {
385 bt_list_del(&iter
->node
);
388 g_hash_table_destroy(enum_declaration
->table
.quark_to_range_set
);
389 bt_declaration_unref(&enum_declaration
->integer_declaration
->p
);
390 g_free(enum_declaration
);
393 struct declaration_enum
*
394 bt_enum_declaration_new(struct declaration_integer
*integer_declaration
)
396 struct declaration_enum
*enum_declaration
;
398 enum_declaration
= g_new(struct declaration_enum
, 1);
400 enum_declaration
->table
.value_to_quark_set
= g_hash_table_new_full(enum_val_hash
,
403 enum_range_set_free
);
404 BT_INIT_LIST_HEAD(&enum_declaration
->table
.range_to_quark
);
405 enum_declaration
->table
.quark_to_range_set
= g_hash_table_new_full(g_direct_hash
,
407 NULL
, enum_range_set_free
);
408 bt_declaration_ref(&integer_declaration
->p
);
409 enum_declaration
->integer_declaration
= integer_declaration
;
410 enum_declaration
->p
.id
= CTF_TYPE_ENUM
;
411 enum_declaration
->p
.alignment
= 1;
412 enum_declaration
->p
.declaration_free
= _enum_declaration_free
;
413 enum_declaration
->p
.definition_new
= _enum_definition_new
;
414 enum_declaration
->p
.definition_free
= _enum_definition_free
;
415 enum_declaration
->p
.ref
= 1;
416 return enum_declaration
;
420 struct bt_definition
*
421 _enum_definition_new(struct bt_declaration
*declaration
,
422 struct definition_scope
*parent_scope
,
423 GQuark field_name
, int index
,
424 const char *root_name
)
426 struct declaration_enum
*enum_declaration
=
427 container_of(declaration
, struct declaration_enum
, p
);
428 struct definition_enum
*_enum
;
429 struct bt_definition
*definition_integer_parent
;
432 _enum
= g_new(struct definition_enum
, 1);
433 bt_declaration_ref(&enum_declaration
->p
);
434 _enum
->p
.declaration
= declaration
;
435 _enum
->declaration
= enum_declaration
;
438 * Use INT_MAX order to ensure that all fields of the parent
439 * scope are seen as being prior to this scope.
441 _enum
->p
.index
= root_name
? INT_MAX
: index
;
442 _enum
->p
.name
= field_name
;
443 _enum
->p
.path
= bt_new_definition_path(parent_scope
, field_name
, root_name
);
444 _enum
->p
.scope
= bt_new_definition_scope(parent_scope
, field_name
, root_name
);
446 ret
= bt_register_field_definition(field_name
, &_enum
->p
,
449 definition_integer_parent
=
450 enum_declaration
->integer_declaration
->p
.definition_new(&enum_declaration
->integer_declaration
->p
,
452 g_quark_from_string("container"), 0, NULL
);
453 _enum
->integer
= container_of(definition_integer_parent
,
454 struct definition_integer
, p
);
459 void _enum_definition_free(struct bt_definition
*definition
)
461 struct definition_enum
*_enum
=
462 container_of(definition
, struct definition_enum
, p
);
464 bt_definition_unref(&_enum
->integer
->p
);
465 bt_free_definition_scope(_enum
->p
.scope
);
466 bt_declaration_unref(_enum
->p
.declaration
);
468 g_array_unref(_enum
->value
);