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