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