Commit | Line | Data |
---|---|---|
10ba5f69 OD |
1 | # SPDX-License-Identifier: MIT |
2 | # | |
3 | # Copyright (c) 2023 Olivier Dion <odion@efficios.com> | |
4 | # Copyright (c) 2024 Philippe Proulx <pproulx@efficios.com> | |
5 | ||
6 | import bt2 | |
7 | ||
8 | _array_elem = object() | |
9 | ||
10 | ||
11 | # Recursively prints the contents of `field` with the indentation level | |
12 | # `indent` and the introduction `intro`. | |
13 | # | |
14 | # `intro` is one of: | |
15 | # | |
16 | # `None`: | |
17 | # No introduction (root field). | |
18 | # | |
19 | # A string: | |
20 | # Structure field member name. | |
21 | # | |
22 | # `_array_elem`: | |
23 | # `field` is an array field element. | |
24 | def _print_field(intro, field, indent=0): | |
25 | indent_str = " " * indent * 2 | |
26 | intro_str = "" | |
27 | ||
28 | if intro is _array_elem: | |
29 | intro_str = "- " | |
30 | elif intro is not None: | |
31 | intro_str = "{}: ".format(intro) | |
32 | ||
33 | if isinstance(field, bt2._StringFieldConst): | |
34 | print('{}{}"{}"'.format(indent_str, intro_str, field)) | |
35 | elif isinstance(field, bt2._StructureFieldConst): | |
36 | print(indent_str + intro_str, end="") | |
37 | ||
38 | if len(field) == 0: | |
39 | # Special case for an empty structure field | |
40 | print("{}") | |
41 | else: | |
42 | if intro is _array_elem: | |
43 | # Structure field is an array field element itself: | |
44 | # print the first element first, and then print the | |
45 | # remaining ones indented. | |
46 | # | |
47 | # Example: | |
48 | # | |
49 | # - meow: "mix" | |
50 | # montant: -23.599312 | |
51 | # bateau: "jacques" | |
52 | sub_field_names = list(field) | |
53 | _print_field(sub_field_names[0], field[sub_field_names[0]], 0) | |
54 | ||
55 | for sub_field_name in sub_field_names[1:]: | |
56 | _print_field(sub_field_name, field[sub_field_name], indent + 1) | |
57 | else: | |
58 | add_indent = 0 | |
59 | ||
60 | if intro is not None: | |
61 | # Structure field has a name (already printed at | |
62 | # this point): print a newline, and then print all | |
63 | # the members indented (one more level): | |
64 | # | |
65 | # Example: | |
66 | # | |
67 | # struct_name: | |
68 | # meow: "mix" | |
69 | # montant: -23.599312 | |
70 | # bateau: "jacques" | |
71 | add_indent = 1 | |
72 | print() | |
73 | ||
74 | for sub_field_name in field: | |
75 | _print_field( | |
76 | sub_field_name, | |
77 | field[sub_field_name], | |
78 | indent + add_indent, | |
79 | ) | |
80 | elif isinstance(field, bt2._ArrayFieldConst): | |
81 | add_indent = 0 | |
82 | ||
83 | if intro is not None: | |
84 | # Array field has an intro: print it, then print a newline, | |
85 | # and then print all the elements indented (one more level). | |
86 | # | |
87 | # Example 1 (parent is an structure field): | |
88 | # | |
89 | # array_name: | |
90 | # - -17 | |
91 | # - "salut" | |
92 | # - 23 | |
93 | # | |
94 | # Example 2 (parent is an array field): | |
95 | # | |
96 | # - | |
97 | # - -17 | |
98 | # - "salut" | |
99 | # - 23 | |
100 | add_indent = 1 | |
101 | print(indent_str + intro_str.rstrip()) | |
102 | ||
103 | for sub_field in field: | |
104 | _print_field(_array_elem, sub_field, indent + add_indent) | |
105 | elif isinstance(field.cls, bt2._IntegerFieldClassConst): | |
106 | # Honor the preferred display base | |
107 | base = field.cls.preferred_display_base | |
108 | print(indent_str + intro_str, end="") | |
109 | ||
110 | if base == 10: | |
111 | print(int(field)) | |
112 | elif base == 16: | |
113 | print(hex(field)) | |
114 | elif base == 8: | |
115 | print(oct(field)) | |
116 | elif base == 2: | |
117 | print(bin(field)) | |
118 | elif isinstance(field, bt2._BitArrayFieldConst): | |
119 | print(indent_str + intro_str + bin(field)) | |
120 | elif isinstance(field, bt2._BoolFieldConst): | |
121 | print(indent_str + intro_str + ("yes" if field else "no")) | |
122 | elif isinstance(field, bt2._RealFieldConst): | |
123 | print("{}{}{:.6f}".format(indent_str, intro_str, float(field))) | |
124 | elif isinstance(field, bt2._OptionFieldConst): | |
125 | if field.has_field: | |
126 | _print_field(intro, field.field, indent) | |
127 | else: | |
128 | # Special case for an option field without a field | |
129 | print("{}{}~".format(indent_str, intro_str)) | |
130 | elif isinstance(field, bt2._VariantFieldConst): | |
131 | _print_field(intro, field.selected_option, indent) | |
132 | else: | |
133 | print(indent_str + intro_str + field) | |
134 | ||
135 | ||
136 | @bt2.plugin_component_class | |
137 | class _SingleSinkComponent(bt2._UserSinkComponent, name="single"): | |
138 | def __init__(self, config, params, obj): | |
139 | self._input = self._add_input_port("input") | |
140 | self._field_name = str(params.get("field-name", "root")) | |
141 | ||
142 | def _user_graph_is_configured(self): | |
143 | self._it = self._create_message_iterator(self._input) | |
144 | ||
145 | def _user_consume(self): | |
146 | msg = next(self._it) | |
147 | ||
148 | if type(msg) is bt2._EventMessageConst: | |
149 | assert self._field_name in msg.event.payload_field | |
150 | assert len(msg.event.payload_field) == 1 | |
151 | _print_field(None, msg.event.payload_field[self._field_name]) | |
152 | ||
153 | ||
154 | bt2.register_plugin(__name__, "test-text") |