Commit | Line | Data |
---|---|---|
6dc2ca62 | 1 | /* |
b1a2f580 | 2 | * types.c |
ccd7e1c8 | 3 | * |
d79865b9 | 4 | * BabelTrace - Converter |
6dc2ca62 MD |
5 | * |
6 | * Types registry. | |
7 | * | |
64fa3fec MD |
8 | * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation |
9 | * | |
10 | * Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | |
de0ba614 | 11 | * |
ccd7e1c8 MD |
12 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
13 | * of this software and associated documentation files (the "Software"), to deal | |
14 | * in the Software without restriction, including without limitation the rights | |
15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
16 | * copies of the Software, and to permit persons to whom the Software is | |
17 | * furnished to do so, subject to the following conditions: | |
de0ba614 | 18 | * |
ccd7e1c8 MD |
19 | * The above copyright notice and this permission notice shall be included in |
20 | * all copies or substantial portions of the Software. | |
c462e188 MD |
21 | * |
22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
28 | * SOFTWARE. | |
6dc2ca62 MD |
29 | */ |
30 | ||
4c8bfb7e | 31 | #include <babeltrace/format.h> |
70bd0a12 | 32 | #include <babeltrace/babeltrace-internal.h> |
3122e6f0 | 33 | #include <babeltrace/types.h> |
8099326b | 34 | #include <babeltrace/compat/limits.h> |
6dc2ca62 | 35 | #include <glib.h> |
d1708134 MD |
36 | #include <errno.h> |
37 | ||
c054553d | 38 | static |
78af2bcd MD |
39 | GQuark prefix_quark(const char *prefix, GQuark quark) |
40 | { | |
41 | GQuark nq; | |
42 | GString *str; | |
15d4fe3c | 43 | char *quark_str; |
78af2bcd MD |
44 | |
45 | str = g_string_new(prefix); | |
46 | g_string_append(str, g_quark_to_string(quark)); | |
15d4fe3c JD |
47 | quark_str = g_string_free(str, FALSE); |
48 | nq = g_quark_from_string(quark_str); | |
49 | g_free(quark_str); | |
78af2bcd MD |
50 | return nq; |
51 | } | |
52 | ||
53 | static | |
ecc54f11 | 54 | struct bt_declaration * |
becd02a1 | 55 | bt_lookup_declaration_scope(GQuark declaration_name, |
f6625916 | 56 | struct declaration_scope *scope) |
d1708134 | 57 | { |
f6625916 MD |
58 | return g_hash_table_lookup(scope->typedef_declarations, |
59 | (gconstpointer) (unsigned long) declaration_name); | |
d1708134 MD |
60 | } |
61 | ||
ecc54f11 | 62 | struct bt_declaration *bt_lookup_declaration(GQuark declaration_name, |
f6625916 | 63 | struct declaration_scope *scope) |
c054553d | 64 | { |
ecc54f11 | 65 | struct bt_declaration *declaration; |
c054553d MD |
66 | |
67 | while (scope) { | |
becd02a1 | 68 | declaration = bt_lookup_declaration_scope(declaration_name, |
78af2bcd MD |
69 | scope); |
70 | if (declaration) | |
71 | return declaration; | |
c054553d MD |
72 | scope = scope->parent_scope; |
73 | } | |
74 | return NULL; | |
75 | } | |
76 | ||
ecc54f11 | 77 | int bt_register_declaration(GQuark name, struct bt_declaration *declaration, |
f6625916 | 78 | struct declaration_scope *scope) |
d1708134 | 79 | { |
64893f33 | 80 | if (!name) |
6ee5115e MD |
81 | return -EPERM; |
82 | ||
c054553d | 83 | /* Only lookup in local scope */ |
becd02a1 | 84 | if (bt_lookup_declaration_scope(name, scope)) |
d1708134 MD |
85 | return -EEXIST; |
86 | ||
f6625916 | 87 | g_hash_table_insert(scope->typedef_declarations, |
64893f33 | 88 | (gpointer) (unsigned long) name, |
f6625916 | 89 | declaration); |
e6b4b4f4 | 90 | bt_declaration_ref(declaration); |
ac88af75 MD |
91 | return 0; |
92 | } | |
93 | ||
94 | static | |
0d69b916 | 95 | struct bt_definition * |
f6625916 MD |
96 | lookup_field_definition_scope(GQuark field_name, |
97 | struct definition_scope *scope) | |
ac88af75 | 98 | { |
e1151715 | 99 | return g_hash_table_lookup(scope->definitions, |
ac88af75 MD |
100 | (gconstpointer) (unsigned long) field_name); |
101 | } | |
102 | ||
05c749e5 MD |
103 | /* |
104 | * Returns the index at which the paths differ. | |
105 | * If the value returned equals len, it means the paths are identical | |
106 | * from index 0 to len-1. | |
107 | */ | |
108 | static int compare_paths(GArray *a, GArray *b, int len) | |
109 | { | |
110 | int i; | |
111 | ||
112 | assert(len <= a->len); | |
113 | assert(len <= b->len); | |
114 | ||
115 | for (i = 0; i < len; i++) { | |
116 | GQuark qa, qb; | |
117 | ||
118 | qa = g_array_index(a, GQuark, i); | |
119 | qb = g_array_index(b, GQuark, i); | |
120 | if (qa != qb) | |
121 | return i; | |
122 | } | |
123 | return i; | |
124 | } | |
125 | ||
126 | static int is_path_child_of(GArray *path, GArray *maybe_parent) | |
127 | { | |
08c82b90 | 128 | int ret; |
98df1c9f MD |
129 | |
130 | if (babeltrace_debug) { | |
08c82b90 | 131 | int i, need_dot = 0; |
98df1c9f MD |
132 | |
133 | printf_debug("Is path \""); | |
134 | for (i = 0; i < path->len; need_dot = 1, i++) | |
135 | printf("%s%s", need_dot ? "." : "", | |
136 | g_quark_to_string(g_array_index(path, GQuark, i))); | |
137 | need_dot = 0; | |
138 | printf("\" child of \""); | |
139 | for (i = 0; i < maybe_parent->len; need_dot = 1, i++) | |
140 | printf("%s%s", need_dot ? "." : "", | |
141 | g_quark_to_string(g_array_index(maybe_parent, GQuark, i))); | |
142 | printf("\" ? "); | |
143 | } | |
144 | ||
145 | if (path->len <= maybe_parent->len) { | |
146 | ret = 0; | |
147 | goto end; | |
148 | } | |
05c749e5 MD |
149 | if (compare_paths(path, maybe_parent, maybe_parent->len) |
150 | == maybe_parent->len) | |
98df1c9f | 151 | ret = 1; |
05c749e5 | 152 | else |
98df1c9f MD |
153 | ret = 0; |
154 | end: | |
155 | if (babeltrace_debug) | |
156 | printf("%s\n", ret ? "Yes" : "No"); | |
157 | return ret; | |
05c749e5 MD |
158 | } |
159 | ||
160 | static struct definition_scope * | |
0d69b916 | 161 | get_definition_scope(const struct bt_definition *definition) |
05c749e5 | 162 | { |
a35173fe | 163 | return definition->scope; |
05c749e5 MD |
164 | } |
165 | ||
166 | /* | |
167 | * OK, here is the fun. We want to lookup a field that is: | |
9e29e16e MD |
168 | * - either in the same dynamic scope: |
169 | * - either in the current scope, but prior to the current field. | |
170 | * - or in a parent scope (or parent of parent ...) still in a field | |
171 | * prior to the current field position within the parents. | |
172 | * - or in a different dynamic scope: | |
173 | * - either in a upper dynamic scope (walk down a targeted scope from | |
174 | * the dynamic scope root) | |
175 | * - or in a lower dynamic scope (failure) | |
176 | * The dynamic scope roots are linked together, so we can access the | |
177 | * parent dynamic scope from the child dynamic scope by walking up to | |
178 | * the parent. | |
05c749e5 MD |
179 | * If we cannot find such a field that is prior to our current path, we |
180 | * return NULL. | |
181 | * | |
182 | * cur_path: the path leading to the variant definition. | |
183 | * lookup_path: the path leading to the enum we want to look for. | |
184 | * scope: the definition scope containing the variant definition. | |
185 | */ | |
0d69b916 | 186 | struct bt_definition * |
2b77e6a6 | 187 | bt_lookup_path_definition(GArray *cur_path, |
a35173fe MD |
188 | GArray *lookup_path, |
189 | struct definition_scope *scope) | |
ac88af75 | 190 | { |
0d69b916 | 191 | struct bt_definition *definition, *lookup_definition; |
05c749e5 MD |
192 | GQuark last; |
193 | int index; | |
ac88af75 | 194 | |
98df1c9f MD |
195 | /* Going up in the hierarchy. Check where we come from. */ |
196 | assert(is_path_child_of(cur_path, scope->scope_path)); | |
197 | assert(cur_path->len - scope->scope_path->len == 1); | |
198 | ||
199 | /* | |
200 | * First, check if the target name is size one, present in | |
201 | * our parent path, located prior to us. | |
202 | */ | |
203 | if (lookup_path->len == 1) { | |
204 | last = g_array_index(lookup_path, GQuark, 0); | |
205 | lookup_definition = lookup_field_definition_scope(last, scope); | |
05c749e5 MD |
206 | last = g_array_index(cur_path, GQuark, cur_path->len - 1); |
207 | definition = lookup_field_definition_scope(last, scope); | |
208 | assert(definition); | |
98df1c9f MD |
209 | if (lookup_definition && lookup_definition->index < definition->index) |
210 | return lookup_definition; | |
211 | else | |
212 | return NULL; | |
213 | } | |
214 | ||
215 | while (scope) { | |
216 | if (is_path_child_of(cur_path, scope->scope_path) && | |
217 | cur_path->len - scope->scope_path->len == 1) { | |
218 | last = g_array_index(cur_path, GQuark, cur_path->len - 1); | |
219 | definition = lookup_field_definition_scope(last, scope); | |
220 | assert(definition); | |
221 | index = definition->index; | |
222 | } else { | |
223 | /* | |
224 | * Getting to a dynamic scope parent. We are | |
225 | * guaranteed that the parent is entirely | |
226 | * located before the child. | |
227 | */ | |
228 | index = -1; | |
229 | } | |
05c749e5 MD |
230 | lookup: |
231 | if (is_path_child_of(lookup_path, scope->scope_path)) { | |
232 | /* Means we can lookup the field in this scope */ | |
233 | last = g_array_index(lookup_path, GQuark, | |
234 | scope->scope_path->len); | |
235 | lookup_definition = lookup_field_definition_scope(last, scope); | |
236 | if (!lookup_definition || ((index != -1) && lookup_definition->index >= index)) | |
237 | return NULL; | |
238 | /* Found it! And it is prior to the current field. */ | |
239 | if (lookup_path->len - scope->scope_path->len == 1) { | |
240 | /* Direct child */ | |
241 | return lookup_definition; | |
242 | } else { | |
243 | scope = get_definition_scope(lookup_definition); | |
244 | /* Check if the definition has a sub-scope */ | |
245 | if (!scope) | |
246 | return NULL; | |
247 | /* | |
248 | * Don't compare index anymore, because we are | |
249 | * going within a scope that has been validated | |
250 | * to be entirely prior to the current scope. | |
251 | */ | |
252 | cur_path = NULL; | |
253 | index = -1; | |
254 | goto lookup; | |
255 | } | |
256 | } else { | |
05c749e5 MD |
257 | /* lookup_path is within an upper scope */ |
258 | cur_path = scope->scope_path; | |
259 | scope = scope->parent_scope; | |
260 | } | |
ac88af75 MD |
261 | } |
262 | return NULL; | |
263 | } | |
264 | ||
0d69b916 | 265 | int bt_register_field_definition(GQuark field_name, struct bt_definition *definition, |
f6625916 | 266 | struct definition_scope *scope) |
ac88af75 | 267 | { |
98df1c9f | 268 | if (!scope || !field_name) |
ac88af75 MD |
269 | return -EPERM; |
270 | ||
271 | /* Only lookup in local scope */ | |
e1151715 | 272 | if (lookup_field_definition_scope(field_name, scope)) |
ac88af75 MD |
273 | return -EEXIST; |
274 | ||
e1151715 | 275 | g_hash_table_insert(scope->definitions, |
ac88af75 | 276 | (gpointer) (unsigned long) field_name, |
e1151715 | 277 | definition); |
98df1c9f | 278 | /* Don't keep reference on definition */ |
d1708134 MD |
279 | return 0; |
280 | } | |
281 | ||
ecc54f11 | 282 | void bt_declaration_ref(struct bt_declaration *declaration) |
4c8bfb7e | 283 | { |
f6625916 | 284 | declaration->ref++; |
4c8bfb7e MD |
285 | } |
286 | ||
ecc54f11 | 287 | void bt_declaration_unref(struct bt_declaration *declaration) |
4c8bfb7e | 288 | { |
ff00cad2 MD |
289 | if (!declaration) |
290 | return; | |
f6625916 MD |
291 | if (!--declaration->ref) |
292 | declaration->declaration_free(declaration); | |
4c8bfb7e MD |
293 | } |
294 | ||
0d69b916 | 295 | void bt_definition_ref(struct bt_definition *definition) |
d1708134 | 296 | { |
e1151715 | 297 | definition->ref++; |
d1708134 MD |
298 | } |
299 | ||
0d69b916 | 300 | void bt_definition_unref(struct bt_definition *definition) |
d1708134 | 301 | { |
ff00cad2 MD |
302 | if (!definition) |
303 | return; | |
e1151715 | 304 | if (!--definition->ref) |
f6625916 | 305 | definition->declaration->definition_free(definition); |
c054553d MD |
306 | } |
307 | ||
f6625916 | 308 | struct declaration_scope * |
becd02a1 | 309 | bt_new_declaration_scope(struct declaration_scope *parent_scope) |
c054553d | 310 | { |
f6625916 | 311 | struct declaration_scope *scope = g_new(struct declaration_scope, 1); |
c054553d | 312 | |
f6625916 | 313 | scope->typedef_declarations = g_hash_table_new_full(g_direct_hash, |
c13cbf74 | 314 | g_direct_equal, NULL, |
e6b4b4f4 | 315 | (GDestroyNotify) bt_declaration_unref); |
f6625916 | 316 | scope->struct_declarations = g_hash_table_new_full(g_direct_hash, |
c13cbf74 | 317 | g_direct_equal, NULL, |
e6b4b4f4 | 318 | (GDestroyNotify) bt_declaration_unref); |
f6625916 | 319 | scope->variant_declarations = g_hash_table_new_full(g_direct_hash, |
c13cbf74 | 320 | g_direct_equal, NULL, |
e6b4b4f4 | 321 | (GDestroyNotify) bt_declaration_unref); |
f6625916 | 322 | scope->enum_declarations = g_hash_table_new_full(g_direct_hash, |
c054553d | 323 | g_direct_equal, NULL, |
e6b4b4f4 | 324 | (GDestroyNotify) bt_declaration_unref); |
64893f33 MD |
325 | scope->parent_scope = parent_scope; |
326 | return scope; | |
327 | } | |
328 | ||
becd02a1 | 329 | void bt_free_declaration_scope(struct declaration_scope *scope) |
64893f33 | 330 | { |
f6625916 MD |
331 | g_hash_table_destroy(scope->enum_declarations); |
332 | g_hash_table_destroy(scope->variant_declarations); | |
333 | g_hash_table_destroy(scope->struct_declarations); | |
334 | g_hash_table_destroy(scope->typedef_declarations); | |
64893f33 MD |
335 | g_free(scope); |
336 | } | |
337 | ||
c13cbf74 | 338 | static |
c8c98132 | 339 | struct declaration_struct *bt_lookup_struct_declaration_scope(GQuark struct_name, |
f6625916 | 340 | struct declaration_scope *scope) |
c13cbf74 | 341 | { |
f6625916 | 342 | return g_hash_table_lookup(scope->struct_declarations, |
c13cbf74 MD |
343 | (gconstpointer) (unsigned long) struct_name); |
344 | } | |
345 | ||
c8c98132 | 346 | struct declaration_struct *bt_lookup_struct_declaration(GQuark struct_name, |
f6625916 | 347 | struct declaration_scope *scope) |
c13cbf74 | 348 | { |
f6625916 | 349 | struct declaration_struct *declaration; |
c13cbf74 MD |
350 | |
351 | while (scope) { | |
c8c98132 | 352 | declaration = bt_lookup_struct_declaration_scope(struct_name, scope); |
f6625916 MD |
353 | if (declaration) |
354 | return declaration; | |
c13cbf74 MD |
355 | scope = scope->parent_scope; |
356 | } | |
357 | return NULL; | |
358 | } | |
359 | ||
c8c98132 | 360 | int bt_register_struct_declaration(GQuark struct_name, |
f6625916 MD |
361 | struct declaration_struct *struct_declaration, |
362 | struct declaration_scope *scope) | |
c13cbf74 | 363 | { |
78af2bcd MD |
364 | GQuark prefix_name; |
365 | int ret; | |
366 | ||
c13cbf74 MD |
367 | if (!struct_name) |
368 | return -EPERM; | |
369 | ||
370 | /* Only lookup in local scope */ | |
c8c98132 | 371 | if (bt_lookup_struct_declaration_scope(struct_name, scope)) |
c13cbf74 MD |
372 | return -EEXIST; |
373 | ||
f6625916 | 374 | g_hash_table_insert(scope->struct_declarations, |
c13cbf74 | 375 | (gpointer) (unsigned long) struct_name, |
f6625916 | 376 | struct_declaration); |
e6b4b4f4 | 377 | bt_declaration_ref(&struct_declaration->p); |
78af2bcd MD |
378 | |
379 | /* Also add in typedef/typealias scopes */ | |
380 | prefix_name = prefix_quark("struct ", struct_name); | |
becd02a1 | 381 | ret = bt_register_declaration(prefix_name, &struct_declaration->p, scope); |
78af2bcd | 382 | assert(!ret); |
c13cbf74 MD |
383 | return 0; |
384 | } | |
385 | ||
386 | static | |
a0720417 | 387 | struct declaration_untagged_variant * |
becd02a1 | 388 | bt_lookup_variant_declaration_scope(GQuark variant_name, |
f6625916 | 389 | struct declaration_scope *scope) |
c13cbf74 | 390 | { |
f6625916 | 391 | return g_hash_table_lookup(scope->variant_declarations, |
c13cbf74 MD |
392 | (gconstpointer) (unsigned long) variant_name); |
393 | } | |
394 | ||
a0720417 | 395 | struct declaration_untagged_variant * |
becd02a1 | 396 | bt_lookup_variant_declaration(GQuark variant_name, |
f6625916 | 397 | struct declaration_scope *scope) |
c13cbf74 | 398 | { |
a0720417 | 399 | struct declaration_untagged_variant *declaration; |
c13cbf74 MD |
400 | |
401 | while (scope) { | |
becd02a1 | 402 | declaration = bt_lookup_variant_declaration_scope(variant_name, scope); |
f6625916 MD |
403 | if (declaration) |
404 | return declaration; | |
c13cbf74 MD |
405 | scope = scope->parent_scope; |
406 | } | |
407 | return NULL; | |
408 | } | |
409 | ||
becd02a1 | 410 | int bt_register_variant_declaration(GQuark variant_name, |
a0720417 | 411 | struct declaration_untagged_variant *untagged_variant_declaration, |
f6625916 | 412 | struct declaration_scope *scope) |
c13cbf74 | 413 | { |
78af2bcd MD |
414 | GQuark prefix_name; |
415 | int ret; | |
416 | ||
c13cbf74 MD |
417 | if (!variant_name) |
418 | return -EPERM; | |
419 | ||
420 | /* Only lookup in local scope */ | |
becd02a1 | 421 | if (bt_lookup_variant_declaration_scope(variant_name, scope)) |
c13cbf74 MD |
422 | return -EEXIST; |
423 | ||
f6625916 | 424 | g_hash_table_insert(scope->variant_declarations, |
c13cbf74 | 425 | (gpointer) (unsigned long) variant_name, |
a0720417 | 426 | untagged_variant_declaration); |
e6b4b4f4 | 427 | bt_declaration_ref(&untagged_variant_declaration->p); |
78af2bcd MD |
428 | |
429 | /* Also add in typedef/typealias scopes */ | |
430 | prefix_name = prefix_quark("variant ", variant_name); | |
becd02a1 | 431 | ret = bt_register_declaration(prefix_name, |
78af2bcd MD |
432 | &untagged_variant_declaration->p, scope); |
433 | assert(!ret); | |
c13cbf74 MD |
434 | return 0; |
435 | } | |
436 | ||
437 | static | |
f6625916 | 438 | struct declaration_enum * |
becd02a1 | 439 | bt_lookup_enum_declaration_scope(GQuark enum_name, |
f6625916 | 440 | struct declaration_scope *scope) |
c13cbf74 | 441 | { |
f6625916 | 442 | return g_hash_table_lookup(scope->enum_declarations, |
c13cbf74 MD |
443 | (gconstpointer) (unsigned long) enum_name); |
444 | } | |
445 | ||
f6625916 | 446 | struct declaration_enum * |
becd02a1 | 447 | bt_lookup_enum_declaration(GQuark enum_name, |
f6625916 | 448 | struct declaration_scope *scope) |
c13cbf74 | 449 | { |
f6625916 | 450 | struct declaration_enum *declaration; |
c13cbf74 MD |
451 | |
452 | while (scope) { | |
becd02a1 | 453 | declaration = bt_lookup_enum_declaration_scope(enum_name, scope); |
f6625916 MD |
454 | if (declaration) |
455 | return declaration; | |
c13cbf74 MD |
456 | scope = scope->parent_scope; |
457 | } | |
458 | return NULL; | |
459 | } | |
460 | ||
becd02a1 | 461 | int bt_register_enum_declaration(GQuark enum_name, |
f6625916 MD |
462 | struct declaration_enum *enum_declaration, |
463 | struct declaration_scope *scope) | |
c13cbf74 | 464 | { |
78af2bcd MD |
465 | GQuark prefix_name; |
466 | int ret; | |
467 | ||
c13cbf74 MD |
468 | if (!enum_name) |
469 | return -EPERM; | |
470 | ||
471 | /* Only lookup in local scope */ | |
becd02a1 | 472 | if (bt_lookup_enum_declaration_scope(enum_name, scope)) |
c13cbf74 MD |
473 | return -EEXIST; |
474 | ||
f6625916 | 475 | g_hash_table_insert(scope->enum_declarations, |
c13cbf74 | 476 | (gpointer) (unsigned long) enum_name, |
f6625916 | 477 | enum_declaration); |
e6b4b4f4 | 478 | bt_declaration_ref(&enum_declaration->p); |
78af2bcd MD |
479 | |
480 | /* Also add in typedef/typealias scopes */ | |
481 | prefix_name = prefix_quark("enum ", enum_name); | |
becd02a1 | 482 | ret = bt_register_declaration(prefix_name, &enum_declaration->p, scope); |
78af2bcd | 483 | assert(!ret); |
c13cbf74 MD |
484 | return 0; |
485 | } | |
486 | ||
9e29e16e | 487 | static struct definition_scope * |
2b77e6a6 | 488 | _bt_new_definition_scope(struct definition_scope *parent_scope, |
9e29e16e | 489 | int scope_path_len) |
64893f33 | 490 | { |
e1151715 | 491 | struct definition_scope *scope = g_new(struct definition_scope, 1); |
64893f33 | 492 | |
98df1c9f MD |
493 | scope->definitions = g_hash_table_new(g_direct_hash, |
494 | g_direct_equal); | |
c054553d | 495 | scope->parent_scope = parent_scope; |
05c749e5 MD |
496 | scope->scope_path = g_array_sized_new(FALSE, TRUE, sizeof(GQuark), |
497 | scope_path_len); | |
498 | g_array_set_size(scope->scope_path, scope_path_len); | |
9e29e16e MD |
499 | return scope; |
500 | } | |
501 | ||
2b77e6a6 | 502 | GQuark bt_new_definition_path(struct definition_scope *parent_scope, |
98df1c9f | 503 | GQuark field_name, const char *root_name) |
31262354 MD |
504 | { |
505 | GQuark path; | |
506 | GString *str; | |
507 | gchar *c_str; | |
98df1c9f | 508 | int need_dot = 0; |
31262354 MD |
509 | |
510 | str = g_string_new(""); | |
98df1c9f MD |
511 | if (root_name) { |
512 | g_string_append(str, root_name); | |
513 | need_dot = 1; | |
514 | } else if (parent_scope) { | |
08c82b90 MD |
515 | int i; |
516 | ||
31262354 MD |
517 | for (i = 0; i < parent_scope->scope_path->len; i++) { |
518 | GQuark q = g_array_index(parent_scope->scope_path, | |
519 | GQuark, i); | |
b7e35bad MD |
520 | if (!q) |
521 | continue; | |
98df1c9f MD |
522 | if (need_dot) |
523 | g_string_append(str, "."); | |
31262354 | 524 | g_string_append(str, g_quark_to_string(q)); |
98df1c9f | 525 | need_dot = 1; |
31262354 MD |
526 | } |
527 | } | |
98df1c9f MD |
528 | if (field_name) { |
529 | if (need_dot) | |
530 | g_string_append(str, "."); | |
b7e35bad | 531 | g_string_append(str, g_quark_to_string(field_name)); |
98df1c9f | 532 | } |
31262354 | 533 | c_str = g_string_free(str, FALSE); |
b7e35bad MD |
534 | if (c_str[0] == '\0') |
535 | return 0; | |
31262354 | 536 | path = g_quark_from_string(c_str); |
98df1c9f | 537 | printf_debug("new definition path: %s\n", c_str); |
31262354 MD |
538 | g_free(c_str); |
539 | return path; | |
540 | } | |
541 | ||
9e29e16e | 542 | struct definition_scope * |
2b77e6a6 | 543 | bt_new_definition_scope(struct definition_scope *parent_scope, |
98df1c9f | 544 | GQuark field_name, const char *root_name) |
9e29e16e MD |
545 | { |
546 | struct definition_scope *scope; | |
9e29e16e | 547 | |
98df1c9f | 548 | if (root_name) { |
2b77e6a6 | 549 | scope = _bt_new_definition_scope(parent_scope, 0); |
dd0365d9 | 550 | bt_append_scope_path(root_name, scope->scope_path); |
98df1c9f MD |
551 | } else { |
552 | int scope_path_len = 1; | |
553 | ||
554 | assert(parent_scope); | |
9e29e16e | 555 | scope_path_len += parent_scope->scope_path->len; |
2b77e6a6 | 556 | scope = _bt_new_definition_scope(parent_scope, scope_path_len); |
98df1c9f | 557 | memcpy(scope->scope_path->data, parent_scope->scope_path->data, |
05c749e5 | 558 | sizeof(GQuark) * (scope_path_len - 1)); |
98df1c9f MD |
559 | g_array_index(scope->scope_path, GQuark, scope_path_len - 1) = |
560 | field_name; | |
561 | } | |
562 | if (babeltrace_debug) { | |
563 | int i, need_dot = 0; | |
564 | ||
565 | printf_debug("new definition scope: "); | |
566 | for (i = 0; i < scope->scope_path->len; need_dot = 1, i++) | |
567 | printf("%s%s", need_dot ? "." : "", | |
568 | g_quark_to_string(g_array_index(scope->scope_path, GQuark, i))); | |
569 | printf("\n"); | |
570 | } | |
c054553d MD |
571 | return scope; |
572 | } | |
573 | ||
d00d17d1 | 574 | /* |
d60cb676 | 575 | * in: path (dot separated), out: q (GArray of GQuark) |
d00d17d1 | 576 | */ |
dd0365d9 | 577 | void bt_append_scope_path(const char *path, GArray *q) |
d00d17d1 MD |
578 | { |
579 | const char *ptrbegin, *ptrend = path; | |
580 | GQuark quark; | |
581 | ||
582 | for (;;) { | |
583 | char *str; | |
584 | size_t len; | |
585 | ||
586 | ptrbegin = ptrend; | |
587 | ptrend = strchr(ptrbegin, '.'); | |
588 | if (!ptrend) | |
589 | break; | |
590 | len = ptrend - ptrbegin; | |
591 | /* Don't accept two consecutive dots */ | |
592 | assert(len != 0); | |
593 | str = g_new(char, len + 1); /* include \0 */ | |
594 | memcpy(str, ptrbegin, len); | |
595 | str[len] = '\0'; | |
596 | quark = g_quark_from_string(str); | |
597 | g_array_append_val(q, quark); | |
598 | g_free(str); | |
427c09b7 | 599 | ptrend++; /* skip current dot */ |
d00d17d1 MD |
600 | } |
601 | /* last. Check for trailing dot (and discard). */ | |
602 | if (ptrbegin[0] != '\0') { | |
603 | quark = g_quark_from_string(ptrbegin); | |
604 | g_array_append_val(q, quark); | |
605 | } | |
606 | } | |
607 | ||
2b77e6a6 | 608 | void bt_free_definition_scope(struct definition_scope *scope) |
c054553d | 609 | { |
05c749e5 | 610 | g_array_free(scope->scope_path, TRUE); |
e1151715 | 611 | g_hash_table_destroy(scope->definitions); |
c054553d | 612 | g_free(scope); |
d1708134 | 613 | } |
a35173fe | 614 | |
0d69b916 | 615 | struct bt_definition *bt_lookup_definition(const struct bt_definition *definition, |
a35173fe MD |
616 | const char *field_name) |
617 | { | |
618 | struct definition_scope *scope = get_definition_scope(definition); | |
619 | ||
620 | if (!scope) | |
621 | return NULL; | |
622 | ||
623 | return lookup_field_definition_scope(g_quark_from_string(field_name), | |
624 | scope); | |
625 | } | |
626 | ||
0d69b916 | 627 | struct definition_integer *bt_lookup_integer(const struct bt_definition *definition, |
a35173fe MD |
628 | const char *field_name, |
629 | int signedness) | |
630 | { | |
0d69b916 | 631 | struct bt_definition *lookup; |
a35173fe MD |
632 | struct definition_integer *lookup_integer; |
633 | ||
2b77e6a6 | 634 | lookup = bt_lookup_definition(definition, field_name); |
a35173fe MD |
635 | if (!lookup) |
636 | return NULL; | |
9a19a512 | 637 | if (lookup->declaration->id != BT_CTF_TYPE_ID_INTEGER) |
a35173fe MD |
638 | return NULL; |
639 | lookup_integer = container_of(lookup, struct definition_integer, p); | |
640 | if (lookup_integer->declaration->signedness != signedness) | |
641 | return NULL; | |
642 | return lookup_integer; | |
643 | } | |
644 | ||
0d69b916 | 645 | struct definition_enum *bt_lookup_enum(const struct bt_definition *definition, |
a35173fe MD |
646 | const char *field_name, |
647 | int signedness) | |
648 | { | |
0d69b916 | 649 | struct bt_definition *lookup; |
a35173fe MD |
650 | struct definition_enum *lookup_enum; |
651 | ||
2b77e6a6 | 652 | lookup = bt_lookup_definition(definition, field_name); |
a35173fe MD |
653 | if (!lookup) |
654 | return NULL; | |
9a19a512 | 655 | if (lookup->declaration->id != BT_CTF_TYPE_ID_ENUM) |
a35173fe MD |
656 | return NULL; |
657 | lookup_enum = container_of(lookup, struct definition_enum, p); | |
658 | if (lookup_enum->integer->declaration->signedness != signedness) | |
659 | return NULL; | |
660 | return lookup_enum; | |
661 | } | |
662 | ||
0d69b916 | 663 | struct bt_definition *bt_lookup_variant(const struct bt_definition *definition, |
a35173fe MD |
664 | const char *field_name) |
665 | { | |
0d69b916 | 666 | struct bt_definition *lookup; |
ebae302b | 667 | struct definition_variant *bt_lookup_variant; |
a35173fe | 668 | |
2b77e6a6 | 669 | lookup = bt_lookup_definition(definition, field_name); |
a35173fe MD |
670 | if (!lookup) |
671 | return NULL; | |
9a19a512 | 672 | if (lookup->declaration->id != BT_CTF_TYPE_ID_VARIANT) |
a35173fe | 673 | return NULL; |
ebae302b JD |
674 | bt_lookup_variant = container_of(lookup, struct definition_variant, p); |
675 | lookup = bt_variant_get_current_field(bt_lookup_variant); | |
a35173fe MD |
676 | assert(lookup); |
677 | return lookup; | |
678 | } |