Fix: add mmap_base_offset to ctf_stream_pos
[babeltrace.git] / types / enum.c
... / ...
CommitLineData
1/*
2 * enum.c
3 *
4 * BabelTrace - Enumeration Type
5 *
6 * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
7 *
8 * Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
9 *
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:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 */
20
21#include <babeltrace/compiler.h>
22#include <babeltrace/format.h>
23#include <babeltrace/types.h>
24#include <stdint.h>
25#include <glib.h>
26
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
35static
36struct definition *_enum_definition_new(struct declaration *declaration,
37 struct definition_scope *parent_scope,
38 GQuark field_name, int index,
39 const char *root_name);
40static
41void _enum_definition_free(struct definition *definition);
42
43static
44void enum_range_set_free(void *ptr)
45{
46 g_array_unref(ptr);
47}
48
49#if (WORD_SIZE == 32)
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}
84#else /* WORD_SIZE != 32 */
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}
113#endif /* WORD_SIZE != 32 */
114
115/*
116 * Returns a GArray or NULL.
117 * Caller must release the GArray with g_array_unref().
118 */
119GArray *enum_uint_to_quark_set(const struct declaration_enum *enum_declaration,
120 uint64_t v)
121{
122 struct enum_range_to_quark *iter;
123 GArray *qs, *ranges = NULL;
124
125 /* Single values lookup */
126 qs = g_hash_table_lookup(enum_declaration->table.value_to_quark_set,
127 get_uint_v(&v));
128
129 /* Range lookup */
130 bt_list_for_each_entry(iter, &enum_declaration->table.range_to_quark, node) {
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,
139 sizeof(GQuark),
140 qs_len + 1);
141 g_array_set_size(ranges, qs_len + 1);
142 if (qs)
143 memcpy(ranges->data, qs->data,
144 sizeof(GQuark) * qs_len);
145 g_array_index(ranges, GQuark, qs_len) = iter->quark;
146 } else {
147 size_t qs_len = ranges->len;
148
149 g_array_set_size(ranges, qs_len + 1);
150 g_array_index(ranges, GQuark, qs_len) = iter->quark;
151 }
152 }
153 if (!ranges) {
154 if (!qs)
155 return NULL;
156 ranges = qs;
157 g_array_ref(ranges);
158 }
159 return ranges;
160}
161
162/*
163 * Returns a GArray or NULL.
164 * Caller must release the GArray with g_array_unref().
165 */
166GArray *enum_int_to_quark_set(const struct declaration_enum *enum_declaration,
167 int64_t v)
168{
169 struct enum_range_to_quark *iter;
170 GArray *qs, *ranges = NULL;
171
172 /* Single values lookup */
173 qs = g_hash_table_lookup(enum_declaration->table.value_to_quark_set,
174 get_int_v(&v));
175
176 /* Range lookup */
177 bt_list_for_each_entry(iter, &enum_declaration->table.range_to_quark, node) {
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,
186 sizeof(GQuark),
187 qs_len + 1);
188 g_array_set_size(ranges, qs_len + 1);
189 if (qs)
190 memcpy(ranges->data, qs->data,
191 sizeof(GQuark) * qs_len);
192 g_array_index(ranges, GQuark, qs_len) = iter->quark;
193 } else {
194 size_t qs_len = ranges->len;
195
196 g_array_set_size(ranges, qs_len + 1);
197 g_array_index(ranges, GQuark, qs_len) = iter->quark;
198 }
199 }
200 if (!ranges) {
201 if (!qs)
202 return NULL;
203 ranges = qs;
204 g_array_ref(ranges);
205 }
206 return ranges;
207}
208
209static
210void enum_unsigned_insert_value_to_quark_set(struct declaration_enum *enum_declaration,
211 uint64_t v, GQuark q)
212{
213 uint64_t *valuep;
214 GArray *array;
215
216 array = g_hash_table_lookup(enum_declaration->table.value_to_quark_set,
217 get_uint_v(&v));
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;
222#if (WORD_SIZE == 32)
223 valuep = g_new(uint64_t, 1);
224 *valuep = v;
225#else /* WORD_SIZE != 32 */
226 valuep = get_uint_v(&v);
227#endif /* WORD_SIZE != 32 */
228 g_hash_table_insert(enum_declaration->table.value_to_quark_set, valuep, array);
229 } else {
230 g_array_set_size(array, array->len + 1);
231 g_array_index(array, GQuark, array->len - 1) = q;
232 }
233}
234
235static
236void enum_signed_insert_value_to_quark_set(struct declaration_enum *enum_declaration,
237 int64_t v, GQuark q)
238{
239 int64_t *valuep;
240 GArray *array;
241
242 array = g_hash_table_lookup(enum_declaration->table.value_to_quark_set,
243 get_int_v(&v));
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;
248#if (WORD_SIZE == 32)
249 valuep = g_new(int64_t, 1);
250 *valuep = v;
251#else /* WORD_SIZE != 32 */
252 valuep = get_int_v(&v);
253#endif /* WORD_SIZE != 32 */
254 g_hash_table_insert(enum_declaration->table.value_to_quark_set, valuep, array);
255 } else {
256 g_array_set_size(array, array->len + 1);
257 g_array_index(array, GQuark, array->len - 1) = q;
258 }
259}
260
261GArray *enum_quark_to_range_set(const struct declaration_enum *enum_declaration,
262 GQuark q)
263{
264 return g_hash_table_lookup(enum_declaration->table.quark_to_range_set,
265 (gconstpointer) (unsigned long) q);
266}
267
268static
269void enum_signed_insert_range_to_quark(struct declaration_enum *enum_declaration,
270 int64_t start, int64_t end, GQuark q)
271{
272 struct enum_range_to_quark *rtoq;
273
274 rtoq = g_new(struct enum_range_to_quark, 1);
275 bt_list_add(&rtoq->node, &enum_declaration->table.range_to_quark);
276 rtoq->range.start._signed = start;
277 rtoq->range.end._signed = end;
278 rtoq->quark = q;
279}
280
281static
282void enum_unsigned_insert_range_to_quark(struct declaration_enum *enum_declaration,
283 uint64_t start, uint64_t end, GQuark q)
284{
285 struct enum_range_to_quark *rtoq;
286
287 rtoq = g_new(struct enum_range_to_quark, 1);
288 bt_list_add(&rtoq->node, &enum_declaration->table.range_to_quark);
289 rtoq->range.start._unsigned = start;
290 rtoq->range.end._unsigned = end;
291 rtoq->quark = q;
292}
293
294void enum_signed_insert(struct declaration_enum *enum_declaration,
295 int64_t start, int64_t end, GQuark q)
296{
297 GArray *array;
298 struct enum_range *range;
299
300 if (start == end) {
301 enum_signed_insert_value_to_quark_set(enum_declaration, start, q);
302 } else {
303 if (start > end) {
304 uint64_t tmp;
305
306 tmp = start;
307 start = end;
308 end = tmp;
309 }
310 enum_signed_insert_range_to_quark(enum_declaration, start, end, q);
311 }
312
313 array = g_hash_table_lookup(enum_declaration->table.quark_to_range_set,
314 (gconstpointer) (unsigned long) q);
315 if (!array) {
316 array = g_array_sized_new(FALSE, TRUE,
317 sizeof(struct enum_range), 1);
318 g_hash_table_insert(enum_declaration->table.quark_to_range_set,
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;
326}
327
328void enum_unsigned_insert(struct declaration_enum *enum_declaration,
329 uint64_t start, uint64_t end, GQuark q)
330{
331 GArray *array;
332 struct enum_range *range;
333
334
335 if (start == end) {
336 enum_unsigned_insert_value_to_quark_set(enum_declaration, start, q);
337 } else {
338 if (start > end) {
339 uint64_t tmp;
340
341 tmp = start;
342 start = end;
343 end = tmp;
344 }
345 enum_unsigned_insert_range_to_quark(enum_declaration, start, end, q);
346 }
347
348 array = g_hash_table_lookup(enum_declaration->table.quark_to_range_set,
349 (gconstpointer) (unsigned long) q);
350 if (!array) {
351 array = g_array_sized_new(FALSE, TRUE,
352 sizeof(struct enum_range), 1);
353 g_hash_table_insert(enum_declaration->table.quark_to_range_set,
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;
361}
362
363size_t enum_get_nr_enumerators(struct declaration_enum *enum_declaration)
364{
365 return g_hash_table_size(enum_declaration->table.quark_to_range_set);
366}
367
368static
369void _enum_declaration_free(struct declaration *declaration)
370{
371 struct declaration_enum *enum_declaration =
372 container_of(declaration, struct declaration_enum, p);
373 struct enum_range_to_quark *iter, *tmp;
374
375 g_hash_table_destroy(enum_declaration->table.value_to_quark_set);
376 bt_list_for_each_entry_safe(iter, tmp, &enum_declaration->table.range_to_quark, node) {
377 bt_list_del(&iter->node);
378 g_free(iter);
379 }
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);
383}
384
385struct declaration_enum *
386 enum_declaration_new(struct declaration_integer *integer_declaration)
387{
388 struct declaration_enum *enum_declaration;
389
390 enum_declaration = g_new(struct declaration_enum, 1);
391
392 enum_declaration->table.value_to_quark_set = g_hash_table_new_full(enum_val_hash,
393 enum_val_equal,
394 enum_val_free,
395 enum_range_set_free);
396 BT_INIT_LIST_HEAD(&enum_declaration->table.range_to_quark);
397 enum_declaration->table.quark_to_range_set = g_hash_table_new_full(g_direct_hash,
398 g_direct_equal,
399 NULL, enum_range_set_free);
400 declaration_ref(&integer_declaration->p);
401 enum_declaration->integer_declaration = integer_declaration;
402 enum_declaration->p.id = CTF_TYPE_ENUM;
403 enum_declaration->p.alignment = 1;
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;
409}
410
411static
412struct definition *
413 _enum_definition_new(struct declaration *declaration,
414 struct definition_scope *parent_scope,
415 GQuark field_name, int index,
416 const char *root_name)
417{
418 struct declaration_enum *enum_declaration =
419 container_of(declaration, struct declaration_enum, p);
420 struct definition_enum *_enum;
421 struct definition *definition_integer_parent;
422 int ret;
423
424 _enum = g_new(struct definition_enum, 1);
425 declaration_ref(&enum_declaration->p);
426 _enum->p.declaration = declaration;
427 _enum->declaration = enum_declaration;
428 _enum->p.ref = 1;
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;
434 _enum->p.name = field_name;
435 _enum->p.path = new_definition_path(parent_scope, field_name, root_name);
436 _enum->p.scope = new_definition_scope(parent_scope, field_name, root_name);
437 _enum->value = NULL;
438 ret = register_field_definition(field_name, &_enum->p,
439 parent_scope);
440 assert(!ret);
441 definition_integer_parent =
442 enum_declaration->integer_declaration->p.definition_new(&enum_declaration->integer_declaration->p,
443 _enum->p.scope,
444 g_quark_from_static_string("container"), 0, NULL);
445 _enum->integer = container_of(definition_integer_parent,
446 struct definition_integer, p);
447 return &_enum->p;
448}
449
450static
451void _enum_definition_free(struct definition *definition)
452{
453 struct definition_enum *_enum =
454 container_of(definition, struct definition_enum, p);
455
456 definition_unref(&_enum->integer->p);
457 free_definition_scope(_enum->p.scope);
458 declaration_unref(_enum->p.declaration);
459 if (_enum->value)
460 g_array_unref(_enum->value);
461 g_free(_enum);
462}
This page took 0.023537 seconds and 4 git commands to generate.