Update generate IO struct work in progress
[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
e19c3d69 25struct declaration *_enum_declaration_new(struct type *type,
c054553d
MD
26 struct declaration_scope *parent_scope);
27static
e19c3d69 28void _enum_declaration_free(struct declaration *declaration);
c054553d 29
d65d8abb
MD
30static
31void enum_range_set_free(void *ptr)
448d3cc7 32{
d65d8abb 33 g_array_unref(ptr);
448d3cc7
MD
34}
35
d65d8abb
MD
36/*
37 * Returns a GArray or NULL.
38 * Caller must release the GArray with g_array_unref().
39 */
e19c3d69 40GArray *enum_uint_to_quark_set(const struct type_enum *enum_type,
d65d8abb 41 uint64_t v)
448d3cc7 42{
d65d8abb
MD
43 struct enum_range_to_quark *iter;
44 GArray *qs, *ranges = NULL;
448d3cc7 45
d65d8abb 46 /* Single values lookup */
e19c3d69 47 qs = g_hash_table_lookup(enum_type->table.value_to_quark_set, &v);
d65d8abb
MD
48
49 /* Range lookup */
e19c3d69 50 cds_list_for_each_entry(iter, &enum_type->table.range_to_quark, node) {
d65d8abb
MD
51 if (iter->range.start._unsigned > v || iter->range.end._unsigned < v)
52 continue;
53 if (!ranges) {
54 size_t qs_len = 0;
55
56 if (qs)
57 qs_len = qs->len;
58 ranges = g_array_sized_new(FALSE, TRUE,
59 sizeof(struct enum_range),
60 qs_len + 1);
61 g_array_set_size(ranges, qs_len + 1);
62 if (qs)
63 memcpy(ranges->data, qs->data,
64 sizeof(struct enum_range) * qs_len);
65 g_array_index(ranges, struct enum_range, qs_len) = iter->range;
66 } else {
67 g_array_set_size(ranges, ranges->len + 1);
68 g_array_index(ranges, struct enum_range, ranges->len) = iter->range;
69 }
70 }
fdacfb73 71 if (!ranges) {
d65d8abb 72 ranges = qs;
fdacfb73
MD
73 g_array_ref(ranges);
74 }
d65d8abb 75 return ranges;
448d3cc7
MD
76}
77
d65d8abb
MD
78/*
79 * Returns a GArray or NULL.
80 * Caller must release the GArray with g_array_unref().
81 */
e19c3d69 82GArray *enum_int_to_quark_set(const struct type_enum *enum_type, uint64_t v)
448d3cc7 83{
d65d8abb
MD
84 struct enum_range_to_quark *iter;
85 GArray *qs, *ranges = NULL;
86
87 /* Single values lookup */
e19c3d69 88 qs = g_hash_table_lookup(enum_type->table.value_to_quark_set, &v);
d65d8abb
MD
89
90 /* Range lookup */
e19c3d69 91 cds_list_for_each_entry(iter, &enum_type->table.range_to_quark, node) {
d65d8abb
MD
92 if (iter->range.start._signed > v || iter->range.end._signed < v)
93 continue;
94 if (!ranges) {
95 size_t qs_len = 0;
96
97 if (qs)
98 qs_len = qs->len;
99 ranges = g_array_sized_new(FALSE, TRUE,
100 sizeof(struct enum_range),
101 qs_len + 1);
102 g_array_set_size(ranges, qs_len + 1);
103 if (qs)
104 memcpy(ranges->data, qs->data,
105 sizeof(struct enum_range) * qs_len);
106 g_array_index(ranges, struct enum_range, qs_len) = iter->range;
107 } else {
108 g_array_set_size(ranges, ranges->len + 1);
109 g_array_index(ranges, struct enum_range, ranges->len) = iter->range;
110 }
111 }
fdacfb73 112 if (!ranges) {
d65d8abb 113 ranges = qs;
fdacfb73
MD
114 g_array_ref(ranges);
115 }
d65d8abb 116 return ranges;
448d3cc7
MD
117}
118
d65d8abb
MD
119#if (__WORDSIZE == 32)
120static
448d3cc7
MD
121guint enum_val_hash(gconstpointer key)
122{
123 int64_t ukey = *(const int64_t *)key;
124
125 return (guint)ukey ^ (guint)(ukey >> 32);
126}
127
d65d8abb 128static
448d3cc7
MD
129gboolean enum_val_equal(gconstpointer a, gconstpointer b)
130{
131 int64_t ua = *(const int64_t *)a;
132 int64_t ub = *(const int64_t *)b;
133
134 return ua == ub;
135}
136
d65d8abb 137static
448d3cc7
MD
138void enum_val_free(void *ptr)
139{
140 g_free(ptr);
141}
142
d65d8abb 143static
e19c3d69 144void enum_signed_insert_value_to_quark_set(struct type_enum *enum_type,
d65d8abb 145 int64_t v, GQuark q)
448d3cc7 146{
d65d8abb
MD
147 int64_t *valuep;
148 GArray *array;
448d3cc7 149
e19c3d69 150 array = g_hash_table_lookup(enum_type->table.value_to_quark_set, &v);
d65d8abb
MD
151 if (!array) {
152 array = g_array_sized_new(FALSE, TRUE, sizeof(GQuark), 1);
153 g_array_set_size(array, 1);
154 g_array_index(array, GQuark, array->len - 1) = q;
155 valuep = g_new(int64_t, 1);
156 *valuep = v;
e19c3d69 157 g_hash_table_insert(enum_type->table.value_to_quark_set, valuep, array);
d65d8abb
MD
158 } else {
159 g_array_set_size(array, array->len + 1);
160 g_array_index(array, GQuark, array->len - 1) = q;
161 }
448d3cc7
MD
162}
163
d65d8abb 164static
e19c3d69 165void enum_unsigned_insert_value_to_quark_set(struct type_enum *enum_type,
d65d8abb 166 uint64_t v, GQuark q)
448d3cc7 167{
d65d8abb
MD
168 uint64_t *valuep;
169 GArray *array;
448d3cc7 170
e19c3d69 171 array = g_hash_table_lookup(enum_type->table.value_to_quark_set, &v);
d65d8abb
MD
172 if (!array) {
173 array = g_array_sized_new(FALSE, TRUE, sizeof(GQuark), 1);
174 g_array_set_size(array, 1);
175 g_array_index(array, GQuark, array->len - 1) = q;
176 valuep = g_new(uint64_t, 1);
177 *valuep = v;
e19c3d69 178 g_hash_table_insert(enum_type->table.value_to_quark_set, valuep, array);
d65d8abb
MD
179 } else {
180 g_array_set_size(array, array->len + 1);
181 g_array_index(array, GQuark, array->len - 1) = q;
182 }
448d3cc7 183}
d65d8abb
MD
184#else /* __WORDSIZE != 32 */
185static
186guint enum_val_hash(gconstpointer key)
448d3cc7 187{
d65d8abb 188 return g_direct_hash(key);
448d3cc7
MD
189}
190
d65d8abb
MD
191static
192gboolean enum_val_equal(gconstpointer a, gconstpointer b)
448d3cc7 193{
d65d8abb 194 return g_direct_equal(a, b);
448d3cc7
MD
195}
196
d65d8abb
MD
197static
198void enum_val_free(void *ptr)
448d3cc7 199{
448d3cc7
MD
200}
201
d65d8abb 202static
e19c3d69 203void enum_signed_insert_value_to_quark_set(struct type_enum *enum_type,
d65d8abb
MD
204 int64_t v, GQuark q)
205{
206 GArray *array;
207
e19c3d69 208 array = g_hash_table_lookup(enum_type->table.value_to_quark_set,
d65d8abb
MD
209 (gconstpointer) v);
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;
e19c3d69 214 g_hash_table_insert(enum_type->table.value_to_quark_set,
380d60b1 215 (gpointer) v, array);
d65d8abb
MD
216 } else {
217 g_array_set_size(array, array->len + 1);
218 g_array_index(array, GQuark, array->len - 1) = q;
219 }
220}
221
222static
e19c3d69 223void enum_unsigned_insert_value_to_quark_set(struct type_enum *enum_type,
d65d8abb 224 uint64_t v, GQuark q)
448d3cc7 225{
d65d8abb
MD
226 GArray *array;
227
e19c3d69 228 array = g_hash_table_lookup(enum_type->table.value_to_quark_set,
d65d8abb
MD
229 (gconstpointer) v);
230 if (!array) {
231 array = g_array_sized_new(FALSE, TRUE, sizeof(GQuark), 1);
232 g_array_set_size(array, 1);
233 g_array_index(array, GQuark, array->len - 1) = q;
e19c3d69 234 g_hash_table_insert(enum_type->table.value_to_quark_set,
380d60b1 235 (gpointer) v, array);
d65d8abb
MD
236 } else {
237 g_array_set_size(array, array->len + 1);
238 g_array_index(array, GQuark, array->len - 1) = q;
239 }
448d3cc7 240}
d65d8abb 241#endif /* __WORDSIZE != 32 */
448d3cc7 242
e19c3d69 243GArray *enum_quark_to_range_set(const struct type_enum *enum_type,
d65d8abb 244 GQuark q)
448d3cc7 245{
e19c3d69 246 return g_hash_table_lookup(enum_type->table.quark_to_range_set,
47e0f2e2 247 (gconstpointer) (unsigned long) q);
448d3cc7
MD
248}
249
d65d8abb 250static
e19c3d69 251void enum_signed_insert_range_to_quark(struct type_enum *enum_type,
d65d8abb 252 int64_t start, int64_t end, GQuark q)
448d3cc7 253{
d65d8abb
MD
254 struct enum_range_to_quark *rtoq;
255
256 rtoq = g_new(struct enum_range_to_quark, 1);
e19c3d69 257 cds_list_add(&rtoq->node, &enum_type->table.range_to_quark);
d65d8abb
MD
258 rtoq->range.start._signed = start;
259 rtoq->range.end._signed = end;
260 rtoq->quark = q;
448d3cc7
MD
261}
262
d65d8abb 263static
e19c3d69 264void enum_unsigned_insert_range_to_quark(struct type_enum *enum_type,
d65d8abb 265 uint64_t start, uint64_t end, GQuark q)
448d3cc7 266{
d65d8abb
MD
267 struct enum_range_to_quark *rtoq;
268
269 rtoq = g_new(struct enum_range_to_quark, 1);
e19c3d69 270 cds_list_add(&rtoq->node, &enum_type->table.range_to_quark);
d65d8abb
MD
271 rtoq->range.start._unsigned = start;
272 rtoq->range.end._unsigned = end;
273 rtoq->quark = q;
448d3cc7
MD
274}
275
e19c3d69 276void enum_signed_insert(struct type_enum *enum_type,
d65d8abb 277 int64_t start, int64_t end, GQuark q)
448d3cc7 278{
d65d8abb
MD
279 GArray *array;
280 struct enum_range *range;
281
282 if (start == end) {
e19c3d69 283 enum_signed_insert_value_to_quark_set(enum_type, start, q);
d65d8abb
MD
284 } else {
285 if (start > end) {
286 uint64_t tmp;
287
288 tmp = start;
289 start = end;
290 end = tmp;
291 }
e19c3d69 292 enum_signed_insert_range_to_quark(enum_type, start, end, q);
d65d8abb
MD
293 }
294
e19c3d69 295 array = g_hash_table_lookup(enum_type->table.quark_to_range_set,
d65d8abb
MD
296 (gconstpointer) (unsigned long) q);
297 if (!array) {
298 array = g_array_sized_new(FALSE, TRUE,
299 sizeof(struct enum_range), 1);
e19c3d69 300 g_hash_table_insert(enum_type->table.quark_to_range_set,
d65d8abb
MD
301 (gpointer) (unsigned long) q,
302 array);
303 }
304 g_array_set_size(array, array->len + 1);
305 range = &g_array_index(array, struct enum_range, array->len - 1);
306 range->start._signed = start;
307 range->end._signed = end;
448d3cc7
MD
308}
309
e19c3d69 310void enum_unsigned_insert(struct type_enum *enum_type,
d65d8abb 311 uint64_t start, uint64_t end, GQuark q)
448d3cc7 312{
d65d8abb
MD
313 GArray *array;
314 struct enum_range *range;
315
316
317 if (start == end) {
e19c3d69 318 enum_unsigned_insert_value_to_quark_set(enum_type, start, q);
d65d8abb
MD
319 } else {
320 if (start > end) {
321 uint64_t tmp;
322
323 tmp = start;
324 start = end;
325 end = tmp;
326 }
e19c3d69 327 enum_unsigned_insert_range_to_quark(enum_type, start, end, q);
d65d8abb
MD
328 }
329
e19c3d69 330 array = g_hash_table_lookup(enum_type->table.quark_to_range_set,
d65d8abb
MD
331 (gconstpointer) (unsigned long) q);
332 if (!array) {
333 array = g_array_sized_new(FALSE, TRUE,
334 sizeof(struct enum_range), 1);
e19c3d69 335 g_hash_table_insert(enum_type->table.quark_to_range_set,
d65d8abb
MD
336 (gpointer) (unsigned long) q,
337 array);
338 }
339 g_array_set_size(array, array->len + 1);
340 range = &g_array_index(array, struct enum_range, array->len - 1);
341 range->start._unsigned = start;
342 range->end._unsigned = end;
448d3cc7 343}
448d3cc7 344
e19c3d69 345size_t enum_get_nr_enumerators(struct type_enum *enum_type)
c054553d 346{
e19c3d69 347 return g_hash_table_size(enum_type->table.quark_to_range_set);
c054553d
MD
348}
349
4c8bfb7e
MD
350void enum_copy(struct stream_pos *dest, const struct format *fdest,
351 struct stream_pos *src, const struct format *fsrc,
e19c3d69 352 struct declaration *declaration)
448d3cc7 353{
e19c3d69
MD
354 struct declaration_enum *_enum =
355 container_of(declaration, struct declaration_enum, p);
356 struct type_enum *enum_type= _enum->type;
47e0f2e2 357 GArray *array;
448d3cc7
MD
358 GQuark v;
359
e19c3d69 360 array = fsrc->enum_read(src, enum_type);
47e0f2e2 361 assert(array);
c054553d
MD
362 /* unref previous array */
363 if (_enum->value)
6ee5115e 364 g_array_unref(_enum->value);
c054553d 365 _enum->value = array;
47e0f2e2
MD
366 /*
367 * Arbitrarily choose the first one.
368 * TODO: use direct underlying type read/write intead. Not doing it for
369 * now to test enum read and write code.
370 */
371 v = g_array_index(array, GQuark, 0);
e19c3d69 372 return fdest->enum_write(dest, enum_type, v);
448d3cc7
MD
373}
374
c054553d 375static
e19c3d69 376void _enum_type_free(struct type *type)
90b676d7 377{
e19c3d69 378 struct type_enum *enum_type =
6ee5115e 379 container_of(type, struct type_enum, p);
d65d8abb
MD
380 struct enum_range_to_quark *iter, *tmp;
381
e19c3d69
MD
382 g_hash_table_destroy(enum_type->table.value_to_quark_set);
383 cds_list_for_each_entry_safe(iter, tmp, &enum_type->table.range_to_quark, node) {
d65d8abb
MD
384 cds_list_del(&iter->node);
385 g_free(iter);
386 }
e19c3d69 387 g_hash_table_destroy(enum_type->table.quark_to_range_set);
6ee5115e 388 type_unref(&enum_type->integer_type->p);
e19c3d69 389 g_free(enum_type);
90b676d7
MD
390}
391
e19c3d69
MD
392struct type_enum *
393 _enum_type_new(const char *name, struct type_integer *integer_type)
448d3cc7 394{
e19c3d69 395 struct type_enum *enum_type;
448d3cc7 396
e19c3d69
MD
397 enum_type = g_new(struct type_enum, 1);
398
399 enum_type->table.value_to_quark_set = g_hash_table_new_full(enum_val_hash,
d65d8abb
MD
400 enum_val_equal,
401 enum_val_free,
402 enum_range_set_free);
e19c3d69
MD
403 CDS_INIT_LIST_HEAD(&enum_type->table.range_to_quark);
404 enum_type->table.quark_to_range_set = g_hash_table_new_full(g_int_hash,
d65d8abb
MD
405 g_int_equal,
406 NULL, enum_range_set_free);
6ee5115e 407 type_ref(&integer_type->p);
e19c3d69 408 enum_type->integer_type = integer_type;
05628561 409 enum_type->p.id = CTF_TYPE_ENUM;
e19c3d69
MD
410 enum_type->p.name = g_quark_from_string(name);
411 enum_type->p.alignment = 1;
412 enum_type->p.copy = enum_copy;
413 enum_type->p.type_free = _enum_type_free;
414 enum_type->p.declaration_new = _enum_declaration_new;
415 enum_type->p.declaration_free = _enum_declaration_free;
416 enum_type->p.ref = 1;
e19c3d69 417 return enum_type;
c054553d
MD
418}
419
420static
e19c3d69
MD
421struct declaration *
422 _enum_declaration_new(struct type *type,
423 struct declaration_scope *parent_scope)
c054553d 424{
e19c3d69
MD
425 struct type_enum *enum_type =
426 container_of(type, struct type_enum, p);
427 struct declaration_enum *_enum;
6ee5115e 428 struct declaration *declaration_integer_parent;
e19c3d69
MD
429
430 _enum = g_new(struct declaration_enum, 1);
431 type_ref(&enum_type->p);
6ee5115e
MD
432 _enum->p.type = type;
433 _enum->type = enum_type;
c054553d
MD
434 _enum->p.ref = 1;
435 _enum->value = NULL;
e19c3d69
MD
436 declaration_integer_parent =
437 enum_type->integer_type->p.declaration_new(&enum_type->integer_type->p,
438 parent_scope);
439 _enum->integer = container_of(declaration_integer_parent,
440 struct declaration_integer, p);
c054553d
MD
441 return &_enum->p;
442}
443
444static
e19c3d69 445void _enum_declaration_free(struct declaration *declaration)
c054553d 446{
e19c3d69
MD
447 struct declaration_enum *_enum =
448 container_of(declaration, struct declaration_enum, p);
c054553d 449
6ee5115e 450 declaration_unref(&_enum->integer->p);
e19c3d69 451 type_unref(_enum->p.type);
c054553d 452 if (_enum->value)
6ee5115e 453 g_array_unref(_enum->value);
c054553d 454 g_free(_enum);
448d3cc7 455}
This page took 0.070568 seconds and 4 git commands to generate.