Implement CTF-IR event fields getters
[babeltrace.git] / formats / ctf / ir / event-fields.c
1 /*
2 * event-fields.c
3 *
4 * Babeltrace CTF Writer
5 *
6 * Copyright 2013 EfficiOS Inc.
7 *
8 * Author: Jérémie Galarneau <jeremie.galarneau@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 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
29 #include <babeltrace/ctf-writer/event-fields.h>
30 #include <babeltrace/ctf-ir/event-fields-internal.h>
31 #include <babeltrace/ctf-ir/event-types-internal.h>
32 #include <babeltrace/compiler.h>
33
34 #define PACKET_LEN_INCREMENT (getpagesize() * 8 * CHAR_BIT)
35
36 static
37 struct bt_ctf_field *bt_ctf_field_integer_create(struct bt_ctf_field_type *);
38 static
39 struct bt_ctf_field *bt_ctf_field_enumeration_create(
40 struct bt_ctf_field_type *);
41 static
42 struct bt_ctf_field *bt_ctf_field_floating_point_create(
43 struct bt_ctf_field_type *);
44 static
45 struct bt_ctf_field *bt_ctf_field_structure_create(
46 struct bt_ctf_field_type *);
47 static
48 struct bt_ctf_field *bt_ctf_field_variant_create(
49 struct bt_ctf_field_type *);
50 static
51 struct bt_ctf_field *bt_ctf_field_array_create(
52 struct bt_ctf_field_type *);
53 static
54 struct bt_ctf_field *bt_ctf_field_sequence_create(
55 struct bt_ctf_field_type *);
56 static
57 struct bt_ctf_field *bt_ctf_field_string_create(struct bt_ctf_field_type *);
58
59 static
60 void bt_ctf_field_destroy(struct bt_ctf_ref *);
61 static
62 void bt_ctf_field_integer_destroy(struct bt_ctf_field *);
63 static
64 void bt_ctf_field_enumeration_destroy(struct bt_ctf_field *);
65 static
66 void bt_ctf_field_floating_point_destroy(struct bt_ctf_field *);
67 static
68 void bt_ctf_field_structure_destroy(struct bt_ctf_field *);
69 static
70 void bt_ctf_field_variant_destroy(struct bt_ctf_field *);
71 static
72 void bt_ctf_field_array_destroy(struct bt_ctf_field *);
73 static
74 void bt_ctf_field_sequence_destroy(struct bt_ctf_field *);
75 static
76 void bt_ctf_field_string_destroy(struct bt_ctf_field *);
77
78 static
79 int bt_ctf_field_generic_validate(struct bt_ctf_field *field);
80 static
81 int bt_ctf_field_structure_validate(struct bt_ctf_field *field);
82 static
83 int bt_ctf_field_variant_validate(struct bt_ctf_field *field);
84 static
85 int bt_ctf_field_enumeration_validate(struct bt_ctf_field *field);
86 static
87 int bt_ctf_field_array_validate(struct bt_ctf_field *field);
88 static
89 int bt_ctf_field_sequence_validate(struct bt_ctf_field *field);
90
91 static
92 int bt_ctf_field_integer_serialize(struct bt_ctf_field *,
93 struct ctf_stream_pos *);
94 static
95 int bt_ctf_field_enumeration_serialize(struct bt_ctf_field *,
96 struct ctf_stream_pos *);
97 static
98 int bt_ctf_field_floating_point_serialize(struct bt_ctf_field *,
99 struct ctf_stream_pos *);
100 static
101 int bt_ctf_field_structure_serialize(struct bt_ctf_field *,
102 struct ctf_stream_pos *);
103 static
104 int bt_ctf_field_variant_serialize(struct bt_ctf_field *,
105 struct ctf_stream_pos *);
106 static
107 int bt_ctf_field_array_serialize(struct bt_ctf_field *,
108 struct ctf_stream_pos *);
109 static
110 int bt_ctf_field_sequence_serialize(struct bt_ctf_field *,
111 struct ctf_stream_pos *);
112 static
113 int bt_ctf_field_string_serialize(struct bt_ctf_field *,
114 struct ctf_stream_pos *);
115
116 static
117 int increase_packet_size(struct ctf_stream_pos *pos);
118
119 static
120 struct bt_ctf_field *(*field_create_funcs[])(
121 struct bt_ctf_field_type *) = {
122 [CTF_TYPE_INTEGER] = bt_ctf_field_integer_create,
123 [CTF_TYPE_ENUM] = bt_ctf_field_enumeration_create,
124 [CTF_TYPE_FLOAT] =
125 bt_ctf_field_floating_point_create,
126 [CTF_TYPE_STRUCT] = bt_ctf_field_structure_create,
127 [CTF_TYPE_VARIANT] = bt_ctf_field_variant_create,
128 [CTF_TYPE_ARRAY] = bt_ctf_field_array_create,
129 [CTF_TYPE_SEQUENCE] = bt_ctf_field_sequence_create,
130 [CTF_TYPE_STRING] = bt_ctf_field_string_create,
131 };
132
133 static
134 void (*field_destroy_funcs[])(struct bt_ctf_field *) = {
135 [CTF_TYPE_INTEGER] = bt_ctf_field_integer_destroy,
136 [CTF_TYPE_ENUM] = bt_ctf_field_enumeration_destroy,
137 [CTF_TYPE_FLOAT] =
138 bt_ctf_field_floating_point_destroy,
139 [CTF_TYPE_STRUCT] = bt_ctf_field_structure_destroy,
140 [CTF_TYPE_VARIANT] = bt_ctf_field_variant_destroy,
141 [CTF_TYPE_ARRAY] = bt_ctf_field_array_destroy,
142 [CTF_TYPE_SEQUENCE] = bt_ctf_field_sequence_destroy,
143 [CTF_TYPE_STRING] = bt_ctf_field_string_destroy,
144 };
145
146 static
147 int (*field_validate_funcs[])(struct bt_ctf_field *) = {
148 [CTF_TYPE_INTEGER] = bt_ctf_field_generic_validate,
149 [CTF_TYPE_ENUM] = bt_ctf_field_enumeration_validate,
150 [CTF_TYPE_FLOAT] = bt_ctf_field_generic_validate,
151 [CTF_TYPE_STRUCT] = bt_ctf_field_structure_validate,
152 [CTF_TYPE_VARIANT] = bt_ctf_field_variant_validate,
153 [CTF_TYPE_ARRAY] = bt_ctf_field_array_validate,
154 [CTF_TYPE_SEQUENCE] = bt_ctf_field_sequence_validate,
155 [CTF_TYPE_STRING] = bt_ctf_field_generic_validate,
156 };
157
158 static
159 int (*field_serialize_funcs[])(struct bt_ctf_field *,
160 struct ctf_stream_pos *) = {
161 [CTF_TYPE_INTEGER] = bt_ctf_field_integer_serialize,
162 [CTF_TYPE_ENUM] = bt_ctf_field_enumeration_serialize,
163 [CTF_TYPE_FLOAT] =
164 bt_ctf_field_floating_point_serialize,
165 [CTF_TYPE_STRUCT] = bt_ctf_field_structure_serialize,
166 [CTF_TYPE_VARIANT] = bt_ctf_field_variant_serialize,
167 [CTF_TYPE_ARRAY] = bt_ctf_field_array_serialize,
168 [CTF_TYPE_SEQUENCE] = bt_ctf_field_sequence_serialize,
169 [CTF_TYPE_STRING] = bt_ctf_field_string_serialize,
170 };
171
172 struct bt_ctf_field *bt_ctf_field_create(struct bt_ctf_field_type *type)
173 {
174 struct bt_ctf_field *field = NULL;
175 enum ctf_type_id type_id;
176
177 if (!type) {
178 goto error;
179 }
180
181 type_id = bt_ctf_field_type_get_type_id(type);
182 if (type_id <= CTF_TYPE_UNKNOWN || type_id >= NR_CTF_TYPES ||
183 bt_ctf_field_type_validate(type)) {
184 goto error;
185 }
186
187 field = field_create_funcs[type_id](type);
188 if (!field) {
189 goto error;
190 }
191
192 /* The type's declaration can't change after this point */
193 bt_ctf_field_type_freeze(type);
194 bt_ctf_field_type_get(type);
195 bt_ctf_ref_init(&field->ref_count);
196 field->type = type;
197 error:
198 return field;
199 }
200
201 void bt_ctf_field_get(struct bt_ctf_field *field)
202 {
203 if (field) {
204 bt_ctf_ref_get(&field->ref_count);
205 }
206 }
207
208 void bt_ctf_field_put(struct bt_ctf_field *field)
209 {
210 if (field) {
211 bt_ctf_ref_put(&field->ref_count, bt_ctf_field_destroy);
212 }
213 }
214
215 struct bt_ctf_field_type *bt_ctf_field_get_type(struct bt_ctf_field *field)
216 {
217 struct bt_ctf_field_type *ret = NULL;
218
219 if (!field) {
220 goto end;
221 }
222
223 ret = field->type;
224 bt_ctf_field_type_get(ret);
225 end:
226 return ret;
227 }
228
229 struct bt_ctf_field *bt_ctf_field_sequence_get_length(
230 struct bt_ctf_field *field)
231 {
232 struct bt_ctf_field *ret = NULL;
233 struct bt_ctf_field_sequence *sequence;
234
235 if (!field) {
236 goto end;
237 }
238
239 if (bt_ctf_field_type_get_type_id(field->type) !=
240 CTF_TYPE_SEQUENCE) {
241 goto end;
242 }
243
244 sequence = container_of(field, struct bt_ctf_field_sequence, parent);
245 ret = sequence->length;
246 bt_ctf_field_get(ret);
247 end:
248 return ret;
249 }
250
251 int bt_ctf_field_sequence_set_length(struct bt_ctf_field *field,
252 struct bt_ctf_field *length_field)
253 {
254 int ret = 0;
255 struct bt_ctf_field_type_integer *length_type;
256 struct bt_ctf_field_integer *length;
257 struct bt_ctf_field_sequence *sequence;
258 uint64_t sequence_length;
259
260 if (!field || !length_field) {
261 ret = -1;
262 goto end;
263 }
264 if (bt_ctf_field_type_get_type_id(length_field->type) !=
265 CTF_TYPE_INTEGER) {
266 ret = -1;
267 goto end;
268 }
269
270 length_type = container_of(length_field->type,
271 struct bt_ctf_field_type_integer, parent);
272 if (length_type->declaration.signedness) {
273 ret = -1;
274 goto end;
275 }
276
277 length = container_of(length_field, struct bt_ctf_field_integer,
278 parent);
279 sequence_length = length->definition.value._unsigned;
280 sequence = container_of(field, struct bt_ctf_field_sequence, parent);
281 if (sequence->elements) {
282 g_ptr_array_free(sequence->elements, TRUE);
283 bt_ctf_field_put(sequence->length);
284 }
285
286 sequence->elements = g_ptr_array_sized_new((size_t)sequence_length);
287 if (!sequence->elements) {
288 ret = -1;
289 goto end;
290 }
291
292 g_ptr_array_set_free_func(sequence->elements,
293 (GDestroyNotify)bt_ctf_field_put);
294 g_ptr_array_set_size(sequence->elements, (size_t)sequence_length);
295 bt_ctf_field_get(length_field);
296 sequence->length = length_field;
297 end:
298 return ret;
299 }
300
301 struct bt_ctf_field *bt_ctf_field_structure_get_field(
302 struct bt_ctf_field *field, const char *name)
303 {
304 struct bt_ctf_field *new_field = NULL;
305 GQuark field_quark;
306 struct bt_ctf_field_structure *structure;
307 struct bt_ctf_field_type_structure *structure_type;
308 struct bt_ctf_field_type *field_type;
309 size_t index;
310
311 if (!field || !name ||
312 bt_ctf_field_type_get_type_id(field->type) !=
313 CTF_TYPE_STRUCT) {
314 goto error;
315 }
316
317 field_quark = g_quark_from_string(name);
318 structure = container_of(field, struct bt_ctf_field_structure, parent);
319 structure_type = container_of(field->type,
320 struct bt_ctf_field_type_structure, parent);
321 field_type = bt_ctf_field_type_structure_get_type(structure_type, name);
322 if (!g_hash_table_lookup_extended(structure->field_name_to_index,
323 GUINT_TO_POINTER(field_quark), NULL, (gpointer *)&index)) {
324 goto error;
325 }
326
327 if (structure->fields->pdata[index]) {
328 new_field = structure->fields->pdata[index];
329 goto end;
330 }
331
332 new_field = bt_ctf_field_create(field_type);
333 if (!new_field) {
334 goto error;
335 }
336
337 structure->fields->pdata[index] = new_field;
338 end:
339 bt_ctf_field_get(new_field);
340 error:
341 return new_field;
342 }
343
344 struct bt_ctf_field *bt_ctf_field_structure_get_field_by_index(
345 struct bt_ctf_field *field, size_t index)
346 {
347 int ret;
348 const char *field_name;
349 struct bt_ctf_field_structure *structure;
350 struct bt_ctf_field_type *structure_type;
351 struct bt_ctf_field_type *field_type = NULL;
352 struct bt_ctf_field *ret_field = NULL;
353
354 if (!field ||
355 bt_ctf_field_type_get_type_id(field->type) != CTF_TYPE_STRUCT) {
356 goto end;
357 }
358
359 structure = container_of(field, struct bt_ctf_field_structure, parent);
360 if (index >= structure->fields->len) {
361 goto error;
362 }
363
364 ret_field = structure->fields->pdata[index];
365 if (ret_field) {
366 goto end;
367 }
368
369 /* Field has not been instanciated yet, create it */
370 structure_type = bt_ctf_field_get_type(field);
371 if (!structure_type) {
372 goto error;
373 }
374
375 ret = bt_ctf_field_type_structure_get_field(structure_type,
376 &field_name, &field_type, index);
377 bt_ctf_field_type_put(structure_type);
378 if (ret) {
379 goto error;
380 }
381
382 ret_field = bt_ctf_field_create(field_type);
383 if (!ret_field) {
384 goto error;
385 }
386
387 structure->fields->pdata[index] = ret_field;
388 end:
389 bt_ctf_field_get(ret_field);
390 error:
391 if (field_type) {
392 bt_ctf_field_type_put(field_type);
393 }
394 return ret_field;
395 }
396
397 BT_HIDDEN
398 int bt_ctf_field_structure_set_field(struct bt_ctf_field *field,
399 const char *name, struct bt_ctf_field *value)
400 {
401 int ret = 0;
402 GQuark field_quark;
403 struct bt_ctf_field_structure *structure;
404 struct bt_ctf_field_type_structure *structure_type;
405 struct bt_ctf_field_type *expected_field_type;
406 size_t index;
407
408 if (!field || !name || !value ||
409 bt_ctf_field_type_get_type_id(field->type) !=
410 CTF_TYPE_STRUCT) {
411 ret = -1;
412 goto end;
413 }
414
415 field_quark = g_quark_from_string(name);
416 structure = container_of(field, struct bt_ctf_field_structure, parent);
417 structure_type = container_of(field->type,
418 struct bt_ctf_field_type_structure, parent);
419 expected_field_type = bt_ctf_field_type_structure_get_type(
420 structure_type, name);
421 if (expected_field_type != value->type) {
422 ret = -1;
423 goto end;
424 }
425
426 if (!g_hash_table_lookup_extended(structure->field_name_to_index,
427 GUINT_TO_POINTER(field_quark), NULL, (gpointer *) &index)) {
428 goto end;
429 }
430
431 if (structure->fields->pdata[index]) {
432 bt_ctf_field_put(structure->fields->pdata[index]);
433 }
434
435 structure->fields->pdata[index] = value;
436 bt_ctf_field_get(value);
437 end:
438 return ret;
439 }
440
441 struct bt_ctf_field *bt_ctf_field_array_get_field(struct bt_ctf_field *field,
442 uint64_t index)
443 {
444 struct bt_ctf_field *new_field = NULL;
445 struct bt_ctf_field_array *array;
446 struct bt_ctf_field_type_array *array_type;
447 struct bt_ctf_field_type *field_type;
448
449 if (!field || bt_ctf_field_type_get_type_id(field->type) !=
450 CTF_TYPE_ARRAY) {
451 goto end;
452 }
453
454 array = container_of(field, struct bt_ctf_field_array, parent);
455 if (index >= array->elements->len) {
456 goto end;
457 }
458
459 array_type = container_of(field->type, struct bt_ctf_field_type_array,
460 parent);
461 field_type = bt_ctf_field_type_array_get_element_type(array_type);
462 if (array->elements->pdata[(size_t)index]) {
463 new_field = array->elements->pdata[(size_t)index];
464 goto end;
465 }
466
467 new_field = bt_ctf_field_create(field_type);
468 bt_ctf_field_get(new_field);
469 array->elements->pdata[(size_t)index] = new_field;
470 end:
471 return new_field;
472 }
473
474 struct bt_ctf_field *bt_ctf_field_sequence_get_field(struct bt_ctf_field *field,
475 uint64_t index)
476 {
477 struct bt_ctf_field *new_field = NULL;
478 struct bt_ctf_field_sequence *sequence;
479 struct bt_ctf_field_type_sequence *sequence_type;
480 struct bt_ctf_field_type *field_type;
481
482 if (!field || bt_ctf_field_type_get_type_id(field->type) !=
483 CTF_TYPE_SEQUENCE) {
484 goto end;
485 }
486
487 sequence = container_of(field, struct bt_ctf_field_sequence, parent);
488 if (!sequence->elements || sequence->elements->len <= index) {
489 goto end;
490 }
491
492 sequence_type = container_of(field->type,
493 struct bt_ctf_field_type_sequence, parent);
494 field_type = bt_ctf_field_type_sequence_get_element_type(sequence_type);
495 if (sequence->elements->pdata[(size_t)index]) {
496 new_field = sequence->elements->pdata[(size_t)index];
497 goto end;
498 }
499
500 new_field = bt_ctf_field_create(field_type);
501 bt_ctf_field_get(new_field);
502 sequence->elements->pdata[(size_t)index] = new_field;
503 end:
504 return new_field;
505 }
506
507 struct bt_ctf_field *bt_ctf_field_variant_get_field(struct bt_ctf_field *field,
508 struct bt_ctf_field *tag_field)
509 {
510 struct bt_ctf_field *new_field = NULL;
511 struct bt_ctf_field_variant *variant;
512 struct bt_ctf_field_type_variant *variant_type;
513 struct bt_ctf_field_type *field_type;
514 struct bt_ctf_field *tag_enum = NULL;
515 struct bt_ctf_field_integer *tag_enum_integer;
516 int64_t tag_enum_value;
517
518 if (!field || !tag_field ||
519 bt_ctf_field_type_get_type_id(field->type) !=
520 CTF_TYPE_VARIANT ||
521 bt_ctf_field_type_get_type_id(tag_field->type) !=
522 CTF_TYPE_ENUM) {
523 goto end;
524 }
525
526 variant = container_of(field, struct bt_ctf_field_variant, parent);
527 variant_type = container_of(field->type,
528 struct bt_ctf_field_type_variant, parent);
529 tag_enum = bt_ctf_field_enumeration_get_container(tag_field);
530 if (!tag_enum) {
531 goto end;
532 }
533
534 tag_enum_integer = container_of(tag_enum, struct bt_ctf_field_integer,
535 parent);
536
537 if (!bt_ctf_field_validate(variant->tag)) {
538 goto end;
539 }
540
541 tag_enum_value = tag_enum_integer->definition.value._signed;
542 field_type = bt_ctf_field_type_variant_get_field_type(variant_type,
543 tag_enum_value);
544 if (!field_type) {
545 goto end;
546 }
547
548 new_field = bt_ctf_field_create(field_type);
549 if (!new_field) {
550 goto end;
551 }
552
553 bt_ctf_field_put(variant->tag);
554 bt_ctf_field_put(variant->payload);
555 bt_ctf_field_get(new_field);
556 bt_ctf_field_get(tag_field);
557 variant->tag = tag_field;
558 variant->payload = new_field;
559 end:
560 bt_ctf_field_put(tag_enum);
561 return new_field;
562 }
563
564 struct bt_ctf_field *bt_ctf_field_enumeration_get_container(
565 struct bt_ctf_field *field)
566 {
567 struct bt_ctf_field *container = NULL;
568 struct bt_ctf_field_enumeration *enumeration;
569
570 if (!field) {
571 goto end;
572 }
573
574 enumeration = container_of(field, struct bt_ctf_field_enumeration,
575 parent);
576 if (!enumeration->payload) {
577 struct bt_ctf_field_type_enumeration *enumeration_type =
578 container_of(field->type,
579 struct bt_ctf_field_type_enumeration, parent);
580 enumeration->payload =
581 bt_ctf_field_create(enumeration_type->container);
582 }
583
584 container = enumeration->payload;
585 bt_ctf_field_get(container);
586 end:
587 return container;
588 }
589
590 const char *bt_ctf_field_enumeration_get_mapping_name(
591 struct bt_ctf_field *field)
592 {
593 int ret;
594 const char *name = NULL;
595 struct bt_ctf_field *container = NULL;
596 struct bt_ctf_field_type *container_type = NULL;
597 struct bt_ctf_field_type_integer *integer_type = NULL;
598 struct bt_ctf_field_type_enumeration *enumeration_type = NULL;
599
600 container = bt_ctf_field_enumeration_get_container(field);
601 if (!container) {
602 goto end;
603 }
604
605 container_type = bt_ctf_field_get_type(container);
606 if (!container_type) {
607 goto error_put_container;
608 }
609
610 integer_type = container_of(container_type,
611 struct bt_ctf_field_type_integer, parent);
612 enumeration_type = container_of(field->type,
613 struct bt_ctf_field_type_enumeration, parent);
614
615 if (integer_type->declaration.signedness) {
616 uint64_t value;
617 ret = bt_ctf_field_unsigned_integer_get_value(container,
618 &value);
619 if (ret) {
620 goto error_put_container_type;
621 }
622
623 name = bt_ctf_field_type_enumeration_get_mapping_name_unsigned(
624 enumeration_type, value);
625 } else {
626 int64_t value;
627 ret = bt_ctf_field_signed_integer_get_value(container,
628 &value);
629 if (ret) {
630 goto error_put_container_type;
631 }
632
633 name = bt_ctf_field_type_enumeration_get_mapping_name_signed(
634 enumeration_type, value);
635 }
636
637 error_put_container_type:
638 bt_ctf_field_type_put(container_type);
639 error_put_container:
640 bt_ctf_field_put(container);
641 end:
642 return name;
643 }
644
645 int bt_ctf_field_signed_integer_get_value(struct bt_ctf_field *field,
646 int64_t *value)
647 {
648 int ret = 0;
649 struct bt_ctf_field_integer *integer;
650 struct bt_ctf_field_type_integer *integer_type;
651
652 if (!field || !value || !field->payload_set ||
653 bt_ctf_field_type_get_type_id(field->type) !=
654 CTF_TYPE_INTEGER) {
655 ret = -1;
656 goto end;
657 }
658
659 integer_type = container_of(field->type,
660 struct bt_ctf_field_type_integer, parent);
661 if (!integer_type->declaration.signedness) {
662 ret = -1;
663 goto end;
664 }
665
666 integer = container_of(field,
667 struct bt_ctf_field_integer, parent);
668 *value = integer->definition.value._signed;
669 end:
670 return ret;
671 }
672
673 int bt_ctf_field_signed_integer_set_value(struct bt_ctf_field *field,
674 int64_t value)
675 {
676 int ret = 0;
677 struct bt_ctf_field_integer *integer;
678 struct bt_ctf_field_type_integer *integer_type;
679 unsigned int size;
680 int64_t min_value, max_value;
681
682 if (!field ||
683 bt_ctf_field_type_get_type_id(field->type) !=
684 CTF_TYPE_INTEGER) {
685 ret = -1;
686 goto end;
687 }
688
689 integer = container_of(field, struct bt_ctf_field_integer, parent);
690 integer_type = container_of(field->type,
691 struct bt_ctf_field_type_integer, parent);
692 if (!integer_type->declaration.signedness) {
693 ret = -1;
694 goto end;
695 }
696
697 size = integer_type->declaration.len;
698 min_value = -((int64_t)1 << (size - 1));
699 max_value = ((int64_t)1 << (size - 1)) - 1;
700 if (value < min_value || value > max_value) {
701 ret = -1;
702 goto end;
703 }
704
705 integer->definition.value._signed = value;
706 integer->parent.payload_set = 1;
707 end:
708 return ret;
709 }
710
711 int bt_ctf_field_unsigned_integer_get_value(struct bt_ctf_field *field,
712 uint64_t *value)
713 {
714 int ret = 0;
715 struct bt_ctf_field_integer *integer;
716 struct bt_ctf_field_type_integer *integer_type;
717
718 if (!field || !value || !field->payload_set ||
719 bt_ctf_field_type_get_type_id(field->type) !=
720 CTF_TYPE_INTEGER) {
721 ret = -1;
722 goto end;
723 }
724
725 integer_type = container_of(field->type,
726 struct bt_ctf_field_type_integer, parent);
727 if (integer_type->declaration.signedness) {
728 ret = -1;
729 goto end;
730 }
731
732 integer = container_of(field,
733 struct bt_ctf_field_integer, parent);
734 *value = integer->definition.value._unsigned;
735 end:
736 return ret;
737 }
738
739 int bt_ctf_field_unsigned_integer_set_value(struct bt_ctf_field *field,
740 uint64_t value)
741 {
742 int ret = 0;
743 struct bt_ctf_field_integer *integer;
744 struct bt_ctf_field_type_integer *integer_type;
745 unsigned int size;
746 uint64_t max_value;
747
748 if (!field ||
749 bt_ctf_field_type_get_type_id(field->type) !=
750 CTF_TYPE_INTEGER) {
751 ret = -1;
752 goto end;
753 }
754
755 integer = container_of(field, struct bt_ctf_field_integer, parent);
756 integer_type = container_of(field->type,
757 struct bt_ctf_field_type_integer, parent);
758 if (integer_type->declaration.signedness) {
759 ret = -1;
760 goto end;
761 }
762
763 size = integer_type->declaration.len;
764 max_value = (size == 64) ? UINT64_MAX : ((uint64_t)1 << size) - 1;
765 if (value > max_value) {
766 ret = -1;
767 goto end;
768 }
769
770 integer->definition.value._unsigned = value;
771 integer->parent.payload_set = 1;
772 end:
773 return ret;
774 }
775
776 int bt_ctf_field_floating_point_get_value(struct bt_ctf_field *field,
777 double *value)
778 {
779 int ret = 0;
780 struct bt_ctf_field_floating_point *floating_point;
781
782 if (!field || !value || !field->payload_set ||
783 bt_ctf_field_type_get_type_id(field->type) !=
784 CTF_TYPE_FLOAT) {
785 ret = -1;
786 goto end;
787 }
788
789 floating_point = container_of(field,
790 struct bt_ctf_field_floating_point, parent);
791 *value = floating_point->definition.value;
792 end:
793 return ret;
794 }
795
796 int bt_ctf_field_floating_point_set_value(struct bt_ctf_field *field,
797 double value)
798 {
799 int ret = 0;
800 struct bt_ctf_field_floating_point *floating_point;
801
802 if (!field ||
803 bt_ctf_field_type_get_type_id(field->type) !=
804 CTF_TYPE_FLOAT) {
805 ret = -1;
806 goto end;
807 }
808 floating_point = container_of(field, struct bt_ctf_field_floating_point,
809 parent);
810 floating_point->definition.value = value;
811 floating_point->parent.payload_set = 1;
812 end:
813 return ret;
814 }
815
816 const char *bt_ctf_field_string_get_value(struct bt_ctf_field *field)
817 {
818 const char *ret = NULL;
819 struct bt_ctf_field_string *string;
820
821 if (!field || !field->payload_set ||
822 bt_ctf_field_type_get_type_id(field->type) !=
823 CTF_TYPE_STRING) {
824 goto end;
825 }
826
827 string = container_of(field,
828 struct bt_ctf_field_string, parent);
829 ret = string->payload->str;
830 end:
831 return ret;
832 }
833
834 int bt_ctf_field_string_set_value(struct bt_ctf_field *field,
835 const char *value)
836 {
837 int ret = 0;
838 struct bt_ctf_field_string *string;
839
840 if (!field || !value ||
841 bt_ctf_field_type_get_type_id(field->type) !=
842 CTF_TYPE_STRING) {
843 ret = -1;
844 goto end;
845 }
846
847 string = container_of(field, struct bt_ctf_field_string, parent);
848 if (string->payload) {
849 g_string_free(string->payload, TRUE);
850 }
851
852 string->payload = g_string_new(value);
853 string->parent.payload_set = 1;
854 end:
855 return ret;
856 }
857
858 BT_HIDDEN
859 int bt_ctf_field_validate(struct bt_ctf_field *field)
860 {
861 int ret = 0;
862 enum ctf_type_id type_id;
863
864 if (!field) {
865 ret = -1;
866 goto end;
867 }
868
869 type_id = bt_ctf_field_type_get_type_id(field->type);
870 if (type_id <= CTF_TYPE_UNKNOWN || type_id >= NR_CTF_TYPES) {
871 ret = -1;
872 goto end;
873 }
874
875 ret = field_validate_funcs[type_id](field);
876 end:
877 return ret;
878 }
879
880 BT_HIDDEN
881 int bt_ctf_field_serialize(struct bt_ctf_field *field,
882 struct ctf_stream_pos *pos)
883 {
884 int ret = 0;
885 enum ctf_type_id type_id;
886
887 if (!field || !pos) {
888 ret = -1;
889 goto end;
890 }
891
892 type_id = bt_ctf_field_type_get_type_id(field->type);
893 if (type_id <= CTF_TYPE_UNKNOWN || type_id >= NR_CTF_TYPES) {
894 ret = -1;
895 goto end;
896 }
897
898 ret = field_serialize_funcs[type_id](field, pos);
899 end:
900 return ret;
901 }
902
903 static
904 struct bt_ctf_field *bt_ctf_field_integer_create(struct bt_ctf_field_type *type)
905 {
906 struct bt_ctf_field_type_integer *integer_type = container_of(type,
907 struct bt_ctf_field_type_integer, parent);
908 struct bt_ctf_field_integer *integer = g_new0(
909 struct bt_ctf_field_integer, 1);
910
911 if (integer) {
912 integer->definition.declaration = &integer_type->declaration;
913 }
914
915 return integer ? &integer->parent : NULL;
916 }
917
918 static
919 struct bt_ctf_field *bt_ctf_field_enumeration_create(
920 struct bt_ctf_field_type *type)
921 {
922 struct bt_ctf_field_enumeration *enumeration = g_new0(
923 struct bt_ctf_field_enumeration, 1);
924
925 return enumeration ? &enumeration->parent : NULL;
926 }
927
928 static
929 struct bt_ctf_field *bt_ctf_field_floating_point_create(
930 struct bt_ctf_field_type *type)
931 {
932 struct bt_ctf_field_floating_point *floating_point;
933 struct bt_ctf_field_type_floating_point *floating_point_type;
934
935 floating_point = g_new0(struct bt_ctf_field_floating_point, 1);
936 if (!floating_point) {
937 goto end;
938 }
939
940 floating_point_type = container_of(type,
941 struct bt_ctf_field_type_floating_point, parent);
942 floating_point->definition.declaration = container_of(
943 type->declaration, struct declaration_float, p);
944
945
946 floating_point->definition.sign = &floating_point->sign;
947 floating_point->sign.declaration = &floating_point_type->sign;
948 floating_point->definition.sign->p.declaration =
949 &floating_point_type->sign.p;
950
951 floating_point->definition.mantissa = &floating_point->mantissa;
952 floating_point->mantissa.declaration = &floating_point_type->mantissa;
953 floating_point->definition.mantissa->p.declaration =
954 &floating_point_type->mantissa.p;
955
956 floating_point->definition.exp = &floating_point->exp;
957 floating_point->exp.declaration = &floating_point_type->exp;
958 floating_point->definition.exp->p.declaration =
959 &floating_point_type->exp.p;
960
961 end:
962 return floating_point ? &floating_point->parent : NULL;
963 }
964
965 static
966 struct bt_ctf_field *bt_ctf_field_structure_create(
967 struct bt_ctf_field_type *type)
968 {
969 struct bt_ctf_field_type_structure *structure_type = container_of(type,
970 struct bt_ctf_field_type_structure, parent);
971 struct bt_ctf_field_structure *structure = g_new0(
972 struct bt_ctf_field_structure, 1);
973 struct bt_ctf_field *field = NULL;
974
975 if (!structure || !structure_type->fields->len) {
976 goto end;
977 }
978
979 structure->field_name_to_index = structure_type->field_name_to_index;
980 structure->fields = g_ptr_array_new_with_free_func(
981 (GDestroyNotify)bt_ctf_field_put);
982 g_ptr_array_set_size(structure->fields,
983 g_hash_table_size(structure->field_name_to_index));
984 field = &structure->parent;
985 end:
986 return field;
987 }
988
989 static
990 struct bt_ctf_field *bt_ctf_field_variant_create(struct bt_ctf_field_type *type)
991 {
992 struct bt_ctf_field_variant *variant = g_new0(
993 struct bt_ctf_field_variant, 1);
994 return variant ? &variant->parent : NULL;
995 }
996
997 static
998 struct bt_ctf_field *bt_ctf_field_array_create(struct bt_ctf_field_type *type)
999 {
1000 struct bt_ctf_field_array *array = g_new0(struct bt_ctf_field_array, 1);
1001 struct bt_ctf_field_type_array *array_type;
1002 unsigned int array_length;
1003
1004 if (!array || !type) {
1005 goto error;
1006 }
1007
1008 array_type = container_of(type, struct bt_ctf_field_type_array, parent);
1009 array_length = array_type->length;
1010 array->elements = g_ptr_array_sized_new(array_length);
1011 if (!array->elements) {
1012 goto error;
1013 }
1014
1015 g_ptr_array_set_free_func(array->elements,
1016 (GDestroyNotify)bt_ctf_field_put);
1017 g_ptr_array_set_size(array->elements, array_length);
1018 return &array->parent;
1019 error:
1020 g_free(array);
1021 return NULL;
1022 }
1023
1024 static
1025 struct bt_ctf_field *bt_ctf_field_sequence_create(
1026 struct bt_ctf_field_type *type)
1027 {
1028 struct bt_ctf_field_sequence *sequence = g_new0(
1029 struct bt_ctf_field_sequence, 1);
1030 return sequence ? &sequence->parent : NULL;
1031 }
1032
1033 static
1034 struct bt_ctf_field *bt_ctf_field_string_create(struct bt_ctf_field_type *type)
1035 {
1036 struct bt_ctf_field_string *string = g_new0(
1037 struct bt_ctf_field_string, 1);
1038 return string ? &string->parent : NULL;
1039 }
1040
1041 static
1042 void bt_ctf_field_destroy(struct bt_ctf_ref *ref)
1043 {
1044 struct bt_ctf_field *field;
1045 struct bt_ctf_field_type *type;
1046 enum ctf_type_id type_id;
1047
1048 if (!ref) {
1049 return;
1050 }
1051
1052 field = container_of(ref, struct bt_ctf_field, ref_count);
1053 type = field->type;
1054 type_id = bt_ctf_field_type_get_type_id(type);
1055 if (type_id <= CTF_TYPE_UNKNOWN ||
1056 type_id >= NR_CTF_TYPES) {
1057 return;
1058 }
1059
1060 field_destroy_funcs[type_id](field);
1061 if (type) {
1062 bt_ctf_field_type_put(type);
1063 }
1064 }
1065
1066 static
1067 void bt_ctf_field_integer_destroy(struct bt_ctf_field *field)
1068 {
1069 struct bt_ctf_field_integer *integer;
1070
1071 if (!field) {
1072 return;
1073 }
1074
1075 integer = container_of(field, struct bt_ctf_field_integer, parent);
1076 g_free(integer);
1077 }
1078
1079 static
1080 void bt_ctf_field_enumeration_destroy(struct bt_ctf_field *field)
1081 {
1082 struct bt_ctf_field_enumeration *enumeration;
1083
1084 if (!field) {
1085 return;
1086 }
1087
1088 enumeration = container_of(field, struct bt_ctf_field_enumeration,
1089 parent);
1090 bt_ctf_field_put(enumeration->payload);
1091 g_free(enumeration);
1092 }
1093
1094 static
1095 void bt_ctf_field_floating_point_destroy(struct bt_ctf_field *field)
1096 {
1097 struct bt_ctf_field_floating_point *floating_point;
1098
1099 if (!field) {
1100 return;
1101 }
1102
1103 floating_point = container_of(field, struct bt_ctf_field_floating_point,
1104 parent);
1105 g_free(floating_point);
1106 }
1107
1108 static
1109 void bt_ctf_field_structure_destroy(struct bt_ctf_field *field)
1110 {
1111 struct bt_ctf_field_structure *structure;
1112
1113 if (!field) {
1114 return;
1115 }
1116
1117 structure = container_of(field, struct bt_ctf_field_structure, parent);
1118 g_ptr_array_free(structure->fields, TRUE);
1119 g_free(structure);
1120 }
1121
1122 static
1123 void bt_ctf_field_variant_destroy(struct bt_ctf_field *field)
1124 {
1125 struct bt_ctf_field_variant *variant;
1126
1127 if (!field) {
1128 return;
1129 }
1130
1131 variant = container_of(field, struct bt_ctf_field_variant, parent);
1132 bt_ctf_field_put(variant->tag);
1133 bt_ctf_field_put(variant->payload);
1134 g_free(variant);
1135 }
1136
1137 static
1138 void bt_ctf_field_array_destroy(struct bt_ctf_field *field)
1139 {
1140 struct bt_ctf_field_array *array;
1141
1142 if (!field) {
1143 return;
1144 }
1145
1146 array = container_of(field, struct bt_ctf_field_array, parent);
1147 g_ptr_array_free(array->elements, TRUE);
1148 g_free(array);
1149 }
1150
1151 static
1152 void bt_ctf_field_sequence_destroy(struct bt_ctf_field *field)
1153 {
1154 struct bt_ctf_field_sequence *sequence;
1155
1156 if (!field) {
1157 return;
1158 }
1159
1160 sequence = container_of(field, struct bt_ctf_field_sequence, parent);
1161 g_ptr_array_free(sequence->elements, TRUE);
1162 bt_ctf_field_put(sequence->length);
1163 g_free(sequence);
1164 }
1165
1166 static
1167 void bt_ctf_field_string_destroy(struct bt_ctf_field *field)
1168 {
1169 struct bt_ctf_field_string *string;
1170 if (!field) {
1171 return;
1172 }
1173
1174 string = container_of(field, struct bt_ctf_field_string, parent);
1175 g_string_free(string->payload, TRUE);
1176 g_free(string);
1177 }
1178
1179 static
1180 int bt_ctf_field_generic_validate(struct bt_ctf_field *field)
1181 {
1182 return (field && field->payload_set) ? 0 : -1;
1183 }
1184
1185 static
1186 int bt_ctf_field_enumeration_validate(struct bt_ctf_field *field)
1187 {
1188 int ret;
1189 struct bt_ctf_field_enumeration *enumeration;
1190
1191 if (!field) {
1192 ret = -1;
1193 goto end;
1194 }
1195
1196 enumeration = container_of(field, struct bt_ctf_field_enumeration,
1197 parent);
1198 if (!enumeration->payload) {
1199 ret = -1;
1200 goto end;
1201 }
1202
1203 ret = bt_ctf_field_validate(enumeration->payload);
1204 end:
1205 return ret;
1206 }
1207
1208 static
1209 int bt_ctf_field_structure_validate(struct bt_ctf_field *field)
1210 {
1211 size_t i;
1212 int ret = 0;
1213 struct bt_ctf_field_structure *structure;
1214
1215 if (!field) {
1216 ret = -1;
1217 goto end;
1218 }
1219
1220 structure = container_of(field, struct bt_ctf_field_structure, parent);
1221 for (i = 0; i < structure->fields->len; i++) {
1222 ret = bt_ctf_field_validate(structure->fields->pdata[i]);
1223 if (ret) {
1224 goto end;
1225 }
1226 }
1227 end:
1228 return ret;
1229 }
1230
1231 static
1232 int bt_ctf_field_variant_validate(struct bt_ctf_field *field)
1233 {
1234 int ret = 0;
1235 struct bt_ctf_field_variant *variant;
1236
1237 if (!field) {
1238 ret = -1;
1239 goto end;
1240 }
1241
1242 variant = container_of(field, struct bt_ctf_field_variant, parent);
1243 ret = bt_ctf_field_validate(variant->payload);
1244 end:
1245 return ret;
1246 }
1247
1248 static
1249 int bt_ctf_field_array_validate(struct bt_ctf_field *field)
1250 {
1251 size_t i;
1252 int ret = 0;
1253 struct bt_ctf_field_array *array;
1254
1255 if (!field) {
1256 ret = -1;
1257 goto end;
1258 }
1259
1260 array = container_of(field, struct bt_ctf_field_array, parent);
1261 for (i = 0; i < array->elements->len; i++) {
1262 ret = bt_ctf_field_validate(array->elements->pdata[i]);
1263 if (ret) {
1264 goto end;
1265 }
1266 }
1267 end:
1268 return ret;
1269 }
1270
1271 static
1272 int bt_ctf_field_sequence_validate(struct bt_ctf_field *field)
1273 {
1274 size_t i;
1275 int ret = 0;
1276 struct bt_ctf_field_sequence *sequence;
1277
1278 if (!field) {
1279 ret = -1;
1280 goto end;
1281 }
1282
1283 sequence = container_of(field, struct bt_ctf_field_sequence, parent);
1284 for (i = 0; i < sequence->elements->len; i++) {
1285 ret = bt_ctf_field_validate(sequence->elements->pdata[i]);
1286 if (ret) {
1287 goto end;
1288 }
1289 }
1290 end:
1291 return ret;
1292 }
1293
1294 static
1295 int bt_ctf_field_integer_serialize(struct bt_ctf_field *field,
1296 struct ctf_stream_pos *pos)
1297 {
1298 int ret = 0;
1299 struct bt_ctf_field_integer *integer = container_of(field,
1300 struct bt_ctf_field_integer, parent);
1301
1302 retry:
1303 ret = ctf_integer_write(&pos->parent, &integer->definition.p);
1304 if (ret == -EFAULT) {
1305 /*
1306 * The field is too large to fit in the current packet's
1307 * remaining space. Bump the packet size and retry.
1308 */
1309 ret = increase_packet_size(pos);
1310 if (ret) {
1311 goto end;
1312 }
1313 goto retry;
1314 }
1315 end:
1316 return ret;
1317 }
1318
1319 static
1320 int bt_ctf_field_enumeration_serialize(struct bt_ctf_field *field,
1321 struct ctf_stream_pos *pos)
1322 {
1323 struct bt_ctf_field_enumeration *enumeration = container_of(
1324 field, struct bt_ctf_field_enumeration, parent);
1325
1326 return bt_ctf_field_serialize(enumeration->payload, pos);
1327 }
1328
1329 static
1330 int bt_ctf_field_floating_point_serialize(struct bt_ctf_field *field,
1331 struct ctf_stream_pos *pos)
1332 {
1333 int ret = 0;
1334 struct bt_ctf_field_floating_point *floating_point = container_of(field,
1335 struct bt_ctf_field_floating_point, parent);
1336
1337 retry:
1338 ret = ctf_float_write(&pos->parent, &floating_point->definition.p);
1339 if (ret == -EFAULT) {
1340 /*
1341 * The field is too large to fit in the current packet's
1342 * remaining space. Bump the packet size and retry.
1343 */
1344 ret = increase_packet_size(pos);
1345 if (ret) {
1346 goto end;
1347 }
1348 goto retry;
1349 }
1350 end:
1351 return ret;
1352 }
1353
1354 static
1355 int bt_ctf_field_structure_serialize(struct bt_ctf_field *field,
1356 struct ctf_stream_pos *pos)
1357 {
1358 size_t i;
1359 int ret = 0;
1360 struct bt_ctf_field_structure *structure = container_of(
1361 field, struct bt_ctf_field_structure, parent);
1362
1363 while (!ctf_pos_access_ok(pos,
1364 offset_align(pos->offset,
1365 field->type->declaration->alignment))) {
1366 ret = increase_packet_size(pos);
1367 if (ret) {
1368 goto end;
1369 }
1370 }
1371
1372 if (!ctf_align_pos(pos, field->type->declaration->alignment)) {
1373 ret = -1;
1374 goto end;
1375 }
1376
1377 for (i = 0; i < structure->fields->len; i++) {
1378 struct bt_ctf_field *field = g_ptr_array_index(
1379 structure->fields, i);
1380
1381 ret = bt_ctf_field_serialize(field, pos);
1382 if (ret) {
1383 break;
1384 }
1385 }
1386 end:
1387 return ret;
1388 }
1389
1390 static
1391 int bt_ctf_field_variant_serialize(struct bt_ctf_field *field,
1392 struct ctf_stream_pos *pos)
1393 {
1394 struct bt_ctf_field_variant *variant = container_of(
1395 field, struct bt_ctf_field_variant, parent);
1396
1397 return bt_ctf_field_serialize(variant->payload, pos);
1398 }
1399
1400 static
1401 int bt_ctf_field_array_serialize(struct bt_ctf_field *field,
1402 struct ctf_stream_pos *pos)
1403 {
1404 size_t i;
1405 int ret = 0;
1406 struct bt_ctf_field_array *array = container_of(
1407 field, struct bt_ctf_field_array, parent);
1408
1409 for (i = 0; i < array->elements->len; i++) {
1410 ret = bt_ctf_field_serialize(
1411 g_ptr_array_index(array->elements, i), pos);
1412 if (ret) {
1413 goto end;
1414 }
1415 }
1416 end:
1417 return ret;
1418 }
1419
1420 static
1421 int bt_ctf_field_sequence_serialize(struct bt_ctf_field *field,
1422 struct ctf_stream_pos *pos)
1423 {
1424 size_t i;
1425 int ret = 0;
1426 struct bt_ctf_field_sequence *sequence = container_of(
1427 field, struct bt_ctf_field_sequence, parent);
1428
1429 for (i = 0; i < sequence->elements->len; i++) {
1430 ret = bt_ctf_field_serialize(
1431 g_ptr_array_index(sequence->elements, i), pos);
1432 if (ret) {
1433 goto end;
1434 }
1435 }
1436 end:
1437 return ret;
1438 }
1439
1440 static
1441 int bt_ctf_field_string_serialize(struct bt_ctf_field *field,
1442 struct ctf_stream_pos *pos)
1443 {
1444 size_t i;
1445 int ret = 0;
1446 struct bt_ctf_field_string *string = container_of(field,
1447 struct bt_ctf_field_string, parent);
1448 struct bt_ctf_field_type *character_type =
1449 get_field_type(FIELD_TYPE_ALIAS_UINT8_T);
1450 struct bt_ctf_field *character = bt_ctf_field_create(character_type);
1451
1452 for (i = 0; i < string->payload->len + 1; i++) {
1453 ret = bt_ctf_field_unsigned_integer_set_value(character,
1454 (uint64_t) string->payload->str[i]);
1455 if (ret) {
1456 goto end;
1457 }
1458
1459 ret = bt_ctf_field_integer_serialize(character, pos);
1460 if (ret) {
1461 goto end;
1462 }
1463 }
1464 end:
1465 bt_ctf_field_put(character);
1466 bt_ctf_field_type_put(character_type);
1467 return ret;
1468 }
1469
1470 static
1471 int increase_packet_size(struct ctf_stream_pos *pos)
1472 {
1473 int ret;
1474
1475 assert(pos);
1476 ret = munmap_align(pos->base_mma);
1477 if (ret) {
1478 goto end;
1479 }
1480
1481 pos->packet_size += PACKET_LEN_INCREMENT;
1482 ret = posix_fallocate(pos->fd, pos->mmap_offset,
1483 pos->packet_size / CHAR_BIT);
1484 if (ret) {
1485 goto end;
1486 }
1487
1488 pos->base_mma = mmap_align(pos->packet_size / CHAR_BIT, pos->prot,
1489 pos->flags, pos->fd, pos->mmap_offset);
1490 if (pos->base_mma == MAP_FAILED) {
1491 ret = -1;
1492 }
1493 end:
1494 return ret;
1495 }
This page took 0.110229 seconds and 4 git commands to generate.