Fix handling of memopen size
[babeltrace.git] / types / enum.c
... / ...
CommitLineData
1/*
2 * enum.c
3 *
4 * BabelTrace - Enumeration Type
5 *
6 * Copyright 2010, 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
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:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 */
18
19#include <babeltrace/compiler.h>
20#include <babeltrace/format.h>
21#include <stdint.h>
22#include <glib.h>
23
24static
25struct definition *_enum_definition_new(struct declaration *declaration,
26 struct definition_scope *parent_scope,
27 GQuark field_name, int index,
28 const char *root_name);
29static
30void _enum_definition_free(struct definition *definition);
31
32static
33void enum_range_set_free(void *ptr)
34{
35 g_array_unref(ptr);
36}
37
38/*
39 * Returns a GArray or NULL.
40 * Caller must release the GArray with g_array_unref().
41 */
42GArray *enum_uint_to_quark_set(const struct declaration_enum *enum_declaration,
43 uint64_t v)
44{
45 struct enum_range_to_quark *iter;
46 GArray *qs, *ranges = NULL;
47
48 /* Single values lookup */
49 qs = g_hash_table_lookup(enum_declaration->table.value_to_quark_set, &v);
50
51 /* Range lookup */
52 cds_list_for_each_entry(iter, &enum_declaration->table.range_to_quark, node) {
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 }
73 if (!ranges) {
74 ranges = qs;
75 g_array_ref(ranges);
76 }
77 return ranges;
78}
79
80/*
81 * Returns a GArray or NULL.
82 * Caller must release the GArray with g_array_unref().
83 */
84GArray *enum_int_to_quark_set(const struct declaration_enum *enum_declaration,
85 uint64_t v)
86{
87 struct enum_range_to_quark *iter;
88 GArray *qs, *ranges = NULL;
89
90 /* Single values lookup */
91 qs = g_hash_table_lookup(enum_declaration->table.value_to_quark_set, &v);
92
93 /* Range lookup */
94 cds_list_for_each_entry(iter, &enum_declaration->table.range_to_quark, node) {
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 }
115 if (!ranges) {
116 ranges = qs;
117 g_array_ref(ranges);
118 }
119 return ranges;
120}
121
122#if (__WORDSIZE == 32)
123static
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
131static
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
140static
141void enum_val_free(void *ptr)
142{
143 g_free(ptr);
144}
145
146static
147void enum_signed_insert_value_to_quark_set(struct declaration_enum *enum_declaration,
148 int64_t v, GQuark q)
149{
150 int64_t *valuep;
151 GArray *array;
152
153 array = g_hash_table_lookup(enum_declaration->table.value_to_quark_set, &v);
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;
160 g_hash_table_insert(enum_declaration->table.value_to_quark_set, valuep, array);
161 } else {
162 g_array_set_size(array, array->len + 1);
163 g_array_index(array, GQuark, array->len - 1) = q;
164 }
165}
166
167static
168void enum_unsigned_insert_value_to_quark_set(struct declaration_enum *enum_declaration,
169 uint64_t v, GQuark q)
170{
171 uint64_t *valuep;
172 GArray *array;
173
174 array = g_hash_table_lookup(enum_declaration->table.value_to_quark_set, &v);
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;
181 g_hash_table_insert(enum_declaration->table.value_to_quark_set, valuep, array);
182 } else {
183 g_array_set_size(array, array->len + 1);
184 g_array_index(array, GQuark, array->len - 1) = q;
185 }
186}
187#else /* __WORDSIZE != 32 */
188static
189guint enum_val_hash(gconstpointer key)
190{
191 return g_direct_hash(key);
192}
193
194static
195gboolean enum_val_equal(gconstpointer a, gconstpointer b)
196{
197 return g_direct_equal(a, b);
198}
199
200static
201void enum_val_free(void *ptr)
202{
203}
204
205static
206void enum_signed_insert_value_to_quark_set(struct declaration_enum *enum_declaration,
207 int64_t v, GQuark q)
208{
209 GArray *array;
210
211 array = g_hash_table_lookup(enum_declaration->table.value_to_quark_set,
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;
217 g_hash_table_insert(enum_declaration->table.value_to_quark_set,
218 (gpointer) v, array);
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
226void enum_unsigned_insert_value_to_quark_set(struct declaration_enum *enum_declaration,
227 uint64_t v, GQuark q)
228{
229 GArray *array;
230
231 array = g_hash_table_lookup(enum_declaration->table.value_to_quark_set,
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;
237 g_hash_table_insert(enum_declaration->table.value_to_quark_set,
238 (gpointer) v, array);
239 } else {
240 g_array_set_size(array, array->len + 1);
241 g_array_index(array, GQuark, array->len - 1) = q;
242 }
243}
244#endif /* __WORDSIZE != 32 */
245
246GArray *enum_quark_to_range_set(const struct declaration_enum *enum_declaration,
247 GQuark q)
248{
249 return g_hash_table_lookup(enum_declaration->table.quark_to_range_set,
250 (gconstpointer) (unsigned long) q);
251}
252
253static
254void enum_signed_insert_range_to_quark(struct declaration_enum *enum_declaration,
255 int64_t start, int64_t end, GQuark q)
256{
257 struct enum_range_to_quark *rtoq;
258
259 rtoq = g_new(struct enum_range_to_quark, 1);
260 cds_list_add(&rtoq->node, &enum_declaration->table.range_to_quark);
261 rtoq->range.start._signed = start;
262 rtoq->range.end._signed = end;
263 rtoq->quark = q;
264}
265
266static
267void enum_unsigned_insert_range_to_quark(struct declaration_enum *enum_declaration,
268 uint64_t start, uint64_t end, GQuark q)
269{
270 struct enum_range_to_quark *rtoq;
271
272 rtoq = g_new(struct enum_range_to_quark, 1);
273 cds_list_add(&rtoq->node, &enum_declaration->table.range_to_quark);
274 rtoq->range.start._unsigned = start;
275 rtoq->range.end._unsigned = end;
276 rtoq->quark = q;
277}
278
279void enum_signed_insert(struct declaration_enum *enum_declaration,
280 int64_t start, int64_t end, GQuark q)
281{
282 GArray *array;
283 struct enum_range *range;
284
285 if (start == end) {
286 enum_signed_insert_value_to_quark_set(enum_declaration, start, q);
287 } else {
288 if (start > end) {
289 uint64_t tmp;
290
291 tmp = start;
292 start = end;
293 end = tmp;
294 }
295 enum_signed_insert_range_to_quark(enum_declaration, start, end, q);
296 }
297
298 array = g_hash_table_lookup(enum_declaration->table.quark_to_range_set,
299 (gconstpointer) (unsigned long) q);
300 if (!array) {
301 array = g_array_sized_new(FALSE, TRUE,
302 sizeof(struct enum_range), 1);
303 g_hash_table_insert(enum_declaration->table.quark_to_range_set,
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;
311}
312
313void enum_unsigned_insert(struct declaration_enum *enum_declaration,
314 uint64_t start, uint64_t end, GQuark q)
315{
316 GArray *array;
317 struct enum_range *range;
318
319
320 if (start == end) {
321 enum_unsigned_insert_value_to_quark_set(enum_declaration, start, q);
322 } else {
323 if (start > end) {
324 uint64_t tmp;
325
326 tmp = start;
327 start = end;
328 end = tmp;
329 }
330 enum_unsigned_insert_range_to_quark(enum_declaration, start, end, q);
331 }
332
333 array = g_hash_table_lookup(enum_declaration->table.quark_to_range_set,
334 (gconstpointer) (unsigned long) q);
335 if (!array) {
336 array = g_array_sized_new(FALSE, TRUE,
337 sizeof(struct enum_range), 1);
338 g_hash_table_insert(enum_declaration->table.quark_to_range_set,
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;
346}
347
348size_t enum_get_nr_enumerators(struct declaration_enum *enum_declaration)
349{
350 return g_hash_table_size(enum_declaration->table.quark_to_range_set);
351}
352
353static
354void _enum_declaration_free(struct declaration *declaration)
355{
356 struct declaration_enum *enum_declaration =
357 container_of(declaration, struct declaration_enum, p);
358 struct enum_range_to_quark *iter, *tmp;
359
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) {
362 cds_list_del(&iter->node);
363 g_free(iter);
364 }
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);
368}
369
370struct declaration_enum *
371 enum_declaration_new(struct declaration_integer *integer_declaration)
372{
373 struct declaration_enum *enum_declaration;
374
375 enum_declaration = g_new(struct declaration_enum, 1);
376
377 enum_declaration->table.value_to_quark_set = g_hash_table_new_full(enum_val_hash,
378 enum_val_equal,
379 enum_val_free,
380 enum_range_set_free);
381 CDS_INIT_LIST_HEAD(&enum_declaration->table.range_to_quark);
382 enum_declaration->table.quark_to_range_set = g_hash_table_new_full(g_direct_hash,
383 g_direct_equal,
384 NULL, enum_range_set_free);
385 declaration_ref(&integer_declaration->p);
386 enum_declaration->integer_declaration = integer_declaration;
387 enum_declaration->p.id = CTF_TYPE_ENUM;
388 enum_declaration->p.alignment = 1;
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;
394}
395
396static
397struct definition *
398 _enum_definition_new(struct declaration *declaration,
399 struct definition_scope *parent_scope,
400 GQuark field_name, int index,
401 const char *root_name)
402{
403 struct declaration_enum *enum_declaration =
404 container_of(declaration, struct declaration_enum, p);
405 struct definition_enum *_enum;
406 struct definition *definition_integer_parent;
407 int ret;
408
409 _enum = g_new(struct definition_enum, 1);
410 declaration_ref(&enum_declaration->p);
411 _enum->p.declaration = declaration;
412 _enum->declaration = enum_declaration;
413 _enum->p.ref = 1;
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;
419 _enum->p.name = field_name;
420 _enum->p.path = new_definition_path(parent_scope, field_name, root_name);
421 _enum->p.scope = new_definition_scope(parent_scope, field_name, root_name);
422 _enum->value = NULL;
423 ret = register_field_definition(field_name, &_enum->p,
424 parent_scope);
425 assert(!ret);
426 definition_integer_parent =
427 enum_declaration->integer_declaration->p.definition_new(&enum_declaration->integer_declaration->p,
428 _enum->p.scope,
429 g_quark_from_static_string("container"), 0, NULL);
430 _enum->integer = container_of(definition_integer_parent,
431 struct definition_integer, p);
432 return &_enum->p;
433}
434
435static
436void _enum_definition_free(struct definition *definition)
437{
438 struct definition_enum *_enum =
439 container_of(definition, struct definition_enum, p);
440
441 definition_unref(&_enum->integer->p);
442 free_definition_scope(_enum->p.scope);
443 declaration_unref(_enum->p.declaration);
444 if (_enum->value)
445 g_array_unref(_enum->value);
446 g_free(_enum);
447}
This page took 0.023193 seconds and 4 git commands to generate.