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