Update sequence (type specifier -> field ref), fix definition lookup
[babeltrace.git] / types / enum.c
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
24 static
25 struct definition *_enum_definition_new(struct declaration *declaration,
26 struct definition_scope *parent_scope,
27 GQuark field_name, int index,
28 const char *root_name);
29 static
30 void _enum_definition_free(struct definition *definition);
31
32 static
33 void 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 */
42 GArray *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 */
84 GArray *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)
123 static
124 guint enum_val_hash(gconstpointer key)
125 {
126 int64_t ukey = *(const int64_t *)key;
127
128 return (guint)ukey ^ (guint)(ukey >> 32);
129 }
130
131 static
132 gboolean 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
140 static
141 void enum_val_free(void *ptr)
142 {
143 g_free(ptr);
144 }
145
146 static
147 void 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
167 static
168 void 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 */
188 static
189 guint enum_val_hash(gconstpointer key)
190 {
191 return g_direct_hash(key);
192 }
193
194 static
195 gboolean enum_val_equal(gconstpointer a, gconstpointer b)
196 {
197 return g_direct_equal(a, b);
198 }
199
200 static
201 void enum_val_free(void *ptr)
202 {
203 }
204
205 static
206 void 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
225 static
226 void 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
246 GArray *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
253 static
254 void 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
266 static
267 void 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
279 void 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
313 void 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
348 size_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
353 static
354 void _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
370 struct 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
396 static
397 struct 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->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->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
435 static
436 void _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 declaration_unref(_enum->p.declaration);
443 if (_enum->value)
444 g_array_unref(_enum->value);
445 g_free(_enum);
446 }
This page took 0.054189 seconds and 5 git commands to generate.