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
);
28 void _enum_definition_free(struct definition
*definition
);
31 void enum_range_set_free(void *ptr
)
37 * Returns a GArray or NULL.
38 * Caller must release the GArray with g_array_unref().
40 GArray
*enum_uint_to_quark_set(const struct declaration_enum
*enum_declaration
,
43 struct enum_range_to_quark
*iter
;
44 GArray
*qs
, *ranges
= NULL
;
46 /* Single values lookup */
47 qs
= g_hash_table_lookup(enum_declaration
->table
.value_to_quark_set
, &v
);
50 cds_list_for_each_entry(iter
, &enum_declaration
->table
.range_to_quark
, node
) {
51 if (iter
->range
.start
._unsigned
> v
|| iter
->range
.end
._unsigned
< v
)
58 ranges
= g_array_sized_new(FALSE
, TRUE
,
59 sizeof(struct enum_range
),
61 g_array_set_size(ranges
, qs_len
+ 1);
63 memcpy(ranges
->data
, qs
->data
,
64 sizeof(struct enum_range
) * qs_len
);
65 g_array_index(ranges
, struct enum_range
, qs_len
) = iter
->range
;
67 g_array_set_size(ranges
, ranges
->len
+ 1);
68 g_array_index(ranges
, struct enum_range
, ranges
->len
) = iter
->range
;
79 * Returns a GArray or NULL.
80 * Caller must release the GArray with g_array_unref().
82 GArray
*enum_int_to_quark_set(const struct declaration_enum
*enum_declaration
,
85 struct enum_range_to_quark
*iter
;
86 GArray
*qs
, *ranges
= NULL
;
88 /* Single values lookup */
89 qs
= g_hash_table_lookup(enum_declaration
->table
.value_to_quark_set
, &v
);
92 cds_list_for_each_entry(iter
, &enum_declaration
->table
.range_to_quark
, node
) {
93 if (iter
->range
.start
._signed
> v
|| iter
->range
.end
._signed
< v
)
100 ranges
= g_array_sized_new(FALSE
, TRUE
,
101 sizeof(struct enum_range
),
103 g_array_set_size(ranges
, qs_len
+ 1);
105 memcpy(ranges
->data
, qs
->data
,
106 sizeof(struct enum_range
) * qs_len
);
107 g_array_index(ranges
, struct enum_range
, qs_len
) = iter
->range
;
109 g_array_set_size(ranges
, ranges
->len
+ 1);
110 g_array_index(ranges
, struct enum_range
, ranges
->len
) = iter
->range
;
120 #if (__WORDSIZE == 32)
122 guint
enum_val_hash(gconstpointer key
)
124 int64_t ukey
= *(const int64_t *)key
;
126 return (guint
)ukey
^ (guint
)(ukey
>> 32);
130 gboolean
enum_val_equal(gconstpointer a
, gconstpointer b
)
132 int64_t ua
= *(const int64_t *)a
;
133 int64_t ub
= *(const int64_t *)b
;
139 void enum_val_free(void *ptr
)
145 void enum_signed_insert_value_to_quark_set(struct declaration_enum
*enum_declaration
,
151 array
= g_hash_table_lookup(enum_declaration
->table
.value_to_quark_set
, &v
);
153 array
= g_array_sized_new(FALSE
, TRUE
, sizeof(GQuark
), 1);
154 g_array_set_size(array
, 1);
155 g_array_index(array
, GQuark
, array
->len
- 1) = q
;
156 valuep
= g_new(int64_t, 1);
158 g_hash_table_insert(enum_declaration
->table
.value_to_quark_set
, valuep
, array
);
160 g_array_set_size(array
, array
->len
+ 1);
161 g_array_index(array
, GQuark
, array
->len
- 1) = q
;
166 void enum_unsigned_insert_value_to_quark_set(struct declaration_enum
*enum_declaration
,
167 uint64_t v
, GQuark q
)
172 array
= g_hash_table_lookup(enum_declaration
->table
.value_to_quark_set
, &v
);
174 array
= g_array_sized_new(FALSE
, TRUE
, sizeof(GQuark
), 1);
175 g_array_set_size(array
, 1);
176 g_array_index(array
, GQuark
, array
->len
- 1) = q
;
177 valuep
= g_new(uint64_t, 1);
179 g_hash_table_insert(enum_declaration
->table
.value_to_quark_set
, valuep
, array
);
181 g_array_set_size(array
, array
->len
+ 1);
182 g_array_index(array
, GQuark
, array
->len
- 1) = q
;
185 #else /* __WORDSIZE != 32 */
187 guint
enum_val_hash(gconstpointer key
)
189 return g_direct_hash(key
);
193 gboolean
enum_val_equal(gconstpointer a
, gconstpointer b
)
195 return g_direct_equal(a
, b
);
199 void enum_val_free(void *ptr
)
204 void enum_signed_insert_value_to_quark_set(struct declaration_enum
*enum_declaration
,
209 array
= g_hash_table_lookup(enum_declaration
->table
.value_to_quark_set
,
212 array
= g_array_sized_new(FALSE
, TRUE
, sizeof(GQuark
), 1);
213 g_array_set_size(array
, 1);
214 g_array_index(array
, GQuark
, array
->len
- 1) = q
;
215 g_hash_table_insert(enum_declaration
->table
.value_to_quark_set
,
216 (gpointer
) v
, array
);
218 g_array_set_size(array
, array
->len
+ 1);
219 g_array_index(array
, GQuark
, array
->len
- 1) = q
;
224 void enum_unsigned_insert_value_to_quark_set(struct declaration_enum
*enum_declaration
,
225 uint64_t v
, GQuark q
)
229 array
= g_hash_table_lookup(enum_declaration
->table
.value_to_quark_set
,
232 array
= g_array_sized_new(FALSE
, TRUE
, sizeof(GQuark
), 1);
233 g_array_set_size(array
, 1);
234 g_array_index(array
, GQuark
, array
->len
- 1) = q
;
235 g_hash_table_insert(enum_declaration
->table
.value_to_quark_set
,
236 (gpointer
) v
, array
);
238 g_array_set_size(array
, array
->len
+ 1);
239 g_array_index(array
, GQuark
, array
->len
- 1) = q
;
242 #endif /* __WORDSIZE != 32 */
244 GArray
*enum_quark_to_range_set(const struct declaration_enum
*enum_declaration
,
247 return g_hash_table_lookup(enum_declaration
->table
.quark_to_range_set
,
248 (gconstpointer
) (unsigned long) q
);
252 void enum_signed_insert_range_to_quark(struct declaration_enum
*enum_declaration
,
253 int64_t start
, int64_t end
, GQuark q
)
255 struct enum_range_to_quark
*rtoq
;
257 rtoq
= g_new(struct enum_range_to_quark
, 1);
258 cds_list_add(&rtoq
->node
, &enum_declaration
->table
.range_to_quark
);
259 rtoq
->range
.start
._signed
= start
;
260 rtoq
->range
.end
._signed
= end
;
265 void enum_unsigned_insert_range_to_quark(struct declaration_enum
*enum_declaration
,
266 uint64_t start
, uint64_t end
, GQuark q
)
268 struct enum_range_to_quark
*rtoq
;
270 rtoq
= g_new(struct enum_range_to_quark
, 1);
271 cds_list_add(&rtoq
->node
, &enum_declaration
->table
.range_to_quark
);
272 rtoq
->range
.start
._unsigned
= start
;
273 rtoq
->range
.end
._unsigned
= end
;
277 void enum_signed_insert(struct declaration_enum
*enum_declaration
,
278 int64_t start
, int64_t end
, GQuark q
)
281 struct enum_range
*range
;
284 enum_signed_insert_value_to_quark_set(enum_declaration
, start
, q
);
293 enum_signed_insert_range_to_quark(enum_declaration
, start
, end
, q
);
296 array
= g_hash_table_lookup(enum_declaration
->table
.quark_to_range_set
,
297 (gconstpointer
) (unsigned long) q
);
299 array
= g_array_sized_new(FALSE
, TRUE
,
300 sizeof(struct enum_range
), 1);
301 g_hash_table_insert(enum_declaration
->table
.quark_to_range_set
,
302 (gpointer
) (unsigned long) q
,
305 g_array_set_size(array
, array
->len
+ 1);
306 range
= &g_array_index(array
, struct enum_range
, array
->len
- 1);
307 range
->start
._signed
= start
;
308 range
->end
._signed
= end
;
311 void enum_unsigned_insert(struct declaration_enum
*enum_declaration
,
312 uint64_t start
, uint64_t end
, GQuark q
)
315 struct enum_range
*range
;
319 enum_unsigned_insert_value_to_quark_set(enum_declaration
, start
, q
);
328 enum_unsigned_insert_range_to_quark(enum_declaration
, start
, end
, q
);
331 array
= g_hash_table_lookup(enum_declaration
->table
.quark_to_range_set
,
332 (gconstpointer
) (unsigned long) q
);
334 array
= g_array_sized_new(FALSE
, TRUE
,
335 sizeof(struct enum_range
), 1);
336 g_hash_table_insert(enum_declaration
->table
.quark_to_range_set
,
337 (gpointer
) (unsigned long) q
,
340 g_array_set_size(array
, array
->len
+ 1);
341 range
= &g_array_index(array
, struct enum_range
, array
->len
- 1);
342 range
->start
._unsigned
= start
;
343 range
->end
._unsigned
= end
;
346 size_t enum_get_nr_enumerators(struct declaration_enum
*enum_declaration
)
348 return g_hash_table_size(enum_declaration
->table
.quark_to_range_set
);
351 void enum_copy(struct stream_pos
*dest
, const struct format
*fdest
,
352 struct stream_pos
*src
, const struct format
*fsrc
,
353 struct definition
*definition
)
355 struct definition_enum
*_enum
=
356 container_of(definition
, struct definition_enum
, p
);
357 struct declaration_enum
*enum_declaration
= _enum
->declaration
;
361 array
= fsrc
->enum_read(src
, enum_declaration
);
363 /* unref previous array */
365 g_array_unref(_enum
->value
);
366 _enum
->value
= array
;
368 * Arbitrarily choose the first one.
369 * TODO: use direct underlying declaration read/write intead. Not doing it for
370 * now to test enum read and write code.
372 v
= g_array_index(array
, GQuark
, 0);
373 return fdest
->enum_write(dest
, enum_declaration
, v
);
377 void _enum_declaration_free(struct 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 cds_list_for_each_entry_safe(iter
, tmp
, &enum_declaration
->table
.range_to_quark
, node
) {
385 cds_list_del(&iter
->node
);
388 g_hash_table_destroy(enum_declaration
->table
.quark_to_range_set
);
389 declaration_unref(&enum_declaration
->integer_declaration
->p
);
390 g_free(enum_declaration
);
393 struct declaration_enum
*
394 _enum_declaration_new(const char *name
, 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 CDS_INIT_LIST_HEAD(&enum_declaration
->table
.range_to_quark
);
405 enum_declaration
->table
.quark_to_range_set
= g_hash_table_new_full(g_int_hash
,
407 NULL
, enum_range_set_free
);
408 declaration_ref(&integer_declaration
->p
);
409 enum_declaration
->integer_declaration
= integer_declaration
;
410 enum_declaration
->p
.id
= CTF_TYPE_ENUM
;
411 enum_declaration
->p
.name
= g_quark_from_string(name
);
412 enum_declaration
->p
.alignment
= 1;
413 enum_declaration
->p
.copy
= enum_copy
;
414 enum_declaration
->p
.declaration_free
= _enum_declaration_free
;
415 enum_declaration
->p
.definition_new
= _enum_definition_new
;
416 enum_declaration
->p
.definition_free
= _enum_definition_free
;
417 enum_declaration
->p
.ref
= 1;
418 return enum_declaration
;
423 _enum_definition_new(struct declaration
*declaration
,
424 struct definition_scope
*parent_scope
)
426 struct declaration_enum
*enum_declaration
=
427 container_of(declaration
, struct declaration_enum
, p
);
428 struct definition_enum
*_enum
;
429 struct definition
*definition_integer_parent
;
431 _enum
= g_new(struct definition_enum
, 1);
432 declaration_ref(&enum_declaration
->p
);
433 _enum
->p
.declaration
= declaration
;
434 _enum
->declaration
= enum_declaration
;
437 definition_integer_parent
=
438 enum_declaration
->integer_declaration
->p
.definition_new(&enum_declaration
->integer_declaration
->p
,
440 _enum
->integer
= container_of(definition_integer_parent
,
441 struct definition_integer
, p
);
446 void _enum_definition_free(struct definition
*definition
)
448 struct definition_enum
*_enum
=
449 container_of(definition
, struct definition_enum
, p
);
451 definition_unref(&_enum
->integer
->p
);
452 declaration_unref(_enum
->p
.declaration
);
454 g_array_unref(_enum
->value
);