3 # Babeltrace reader interface Python module
5 # Copyright 2012-2015 EfficiOS Inc.
7 # Author: Danny Serres <danny.serres@efficios.com>
8 # Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
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:
17 # The above copyright notice and this permission notice shall be included in
18 # all copies or substantial portions of the Software.
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
28 import babeltrace
.nativebt
as nbt
29 import babeltrace
.common
as common
32 from datetime
import datetime
35 class TraceCollection
:
37 A :class:`TraceCollection` is a collection of opened traces.
39 Once a trace collection is created, you can add traces to the
40 collection by using the :meth:`add_trace` or
41 :meth:`add_traces_recursive`, and then iterate on the merged
42 events using :attr:`events`.
44 You may use :meth:`remove_trace` to close and remove a specific
45 trace from a trace collection.
48 def __init__(self
, intersect_mode
=False):
50 Creates an empty trace collection.
53 self
._tc
= nbt
._bt
_context
_create
()
54 self
._intersect
_mode
= intersect_mode
57 nbt
._bt
_context
_put
(self
._tc
)
59 def add_trace(self
, path
, format_str
):
61 Adds a trace to the trace collection.
63 *path* is the exact path of the trace on the filesystem.
65 *format_str* is a string indicating the type of trace to
66 add. ``ctf`` is currently the only supported trace format.
68 Returns the corresponding :class:`TraceHandle` instance for
69 this opened trace on success, or ``None`` on error.
71 This function **does not** recurse directories to find a
72 trace. See :meth:`add_traces_recursive` for a recursive
73 version of this function.
76 ret
= nbt
._bt
_context
_add
_trace
(self
._tc
, path
, format_str
,
82 th
= TraceHandle
.__new
__(TraceHandle
)
84 th
._trace
_collection
= self
88 def add_traces_recursive(self
, path
, format_str
):
90 Adds traces to this trace collection by recursively searching
91 in the *path* directory.
93 *format_str* is a string indicating the type of trace to add.
94 ``ctf`` is currently the only supported trace format.
96 Returns a :class:`dict` object mapping full paths to trace
97 handles for each trace found, or ``None`` on error.
99 See also :meth:`add_trace`.
106 for fullpath
, dirs
, files
in os
.walk(path
):
107 if "metadata" in files
:
108 trace_handle
= self
.add_trace(fullpath
, format_str
)
110 if trace_handle
is None:
114 trace_handles
[fullpath
] = trace_handle
117 if noTrace
and error
:
122 def remove_trace(self
, trace_handle
):
124 Removes a trace from the trace collection using its trace
125 handle *trace_handle*.
127 :class:`TraceHandle` objects are returned by :meth:`add_trace`
128 and :meth:`add_traces_recursive`.
132 nbt
._bt
_context
_remove
_trace
(self
._tc
, trace_handle
._id
)
133 except AttributeError:
134 raise TypeError("in remove_trace, argument 2 must be a TraceHandle instance")
137 def intersect_mode(self
):
138 return self
._intersect
_mode
143 Generates the ordered :class:`Event` objects of all the opened
144 traces contained in this trace collection.
146 Due to limitations of the native Babeltrace API, only one event
147 may be "alive" at a given time, i.e. a user **should never**
148 store a copy of the events returned by this function for
149 ulterior use. Users shall make sure to copy the information
150 they need *from* an event before accessing the next one.
153 begin_pos_ptr
= nbt
._bt
_python
_create
_iter
_pos
()
154 end_pos_ptr
= nbt
._bt
_python
_create
_iter
_pos
()
156 if not self
.intersect_mode
:
157 begin_pos_ptr
.type = nbt
.SEEK_BEGIN
158 end_pos_ptr
.type = nbt
.SEEK_LAST
160 for event
in self
._events
(begin_pos_ptr
, end_pos_ptr
):
163 nbt
._bt
_iter
_free
_pos
(begin_pos_ptr
)
164 nbt
._bt
_iter
_free
_pos
(end_pos_ptr
)
166 def events_timestamps(self
, timestamp_begin
, timestamp_end
):
168 Generates the ordered :class:`Event` objects of all the opened
169 traces contained in this trace collection from *timestamp_begin*
172 *timestamp_begin* and *timestamp_end* are given in nanoseconds
175 See :attr:`events` for notes and limitations.
178 begin_pos_ptr
= nbt
._bt
_python
_create
_iter
_pos
()
179 end_pos_ptr
= nbt
._bt
_python
_create
_iter
_pos
()
180 begin_pos_ptr
.type = end_pos_ptr
.type = nbt
.SEEK_TIME
181 begin_pos_ptr
.u
.seek_time
= timestamp_begin
182 end_pos_ptr
.u
.seek_time
= timestamp_end
184 for event
in self
._events
(begin_pos_ptr
, end_pos_ptr
):
187 nbt
._bt
_iter
_free
_pos
(begin_pos_ptr
)
188 nbt
._bt
_iter
_free
_pos
(end_pos_ptr
)
191 def timestamp_begin(self
):
193 Begin timestamp of this trace collection (nanoseconds since
197 pos_ptr
= nbt
._bt
_iter
_pos
()
198 pos_ptr
.type = nbt
.SEEK_BEGIN
200 return self
._timestamp
_at
_pos
(pos_ptr
)
203 def timestamp_end(self
):
205 End timestamp of this trace collection (nanoseconds since
209 pos_ptr
= nbt
._bt
_iter
_pos
()
210 pos_ptr
.type = nbt
.SEEK_LAST
212 return self
._timestamp
_at
_pos
(pos_ptr
)
214 def _timestamp_at_pos(self
, pos_ptr
):
215 ctf_it_ptr
= nbt
._bt
_ctf
_iter
_create
(self
._tc
, pos_ptr
, pos_ptr
)
217 if ctf_it_ptr
is None:
218 raise NotImplementedError("Creation of multiple iterators is unsupported.")
220 ev_ptr
= nbt
._bt
_ctf
_iter
_read
_event
(ctf_it_ptr
)
221 nbt
._bt
_ctf
_iter
_destroy
(ctf_it_ptr
)
223 ev
= Event
.__new
__(Event
)
228 def _events(self
, begin_pos_ptr
, end_pos_ptr
):
229 if self
.intersect_mode
:
230 has_intersection
= nbt
._bt
_python
_has
_intersection
(self
._tc
)
231 if not has_intersection
:
232 # There are no events to provide.
235 ctf_it_ptr
= nbt
._bt
_python
_ctf
_iter
_create
_intersect
(
236 self
._tc
, begin_pos_ptr
, end_pos_ptr
239 ctf_it_ptr
= nbt
._bt
_ctf
_iter
_create
(
240 self
._tc
, begin_pos_ptr
, end_pos_ptr
243 if ctf_it_ptr
is None:
244 raise NotImplementedError("Creation of multiple iterators is unsupported.")
247 ev_ptr
= nbt
._bt
_ctf
_iter
_read
_event
(ctf_it_ptr
)
252 ev
= Event
.__new
__(Event
)
257 except GeneratorExit
:
260 ret
= nbt
._bt
_iter
_next
(nbt
._bt
_ctf
_get
_iter
(ctf_it_ptr
))
265 nbt
._bt
_ctf
_iter
_destroy
(ctf_it_ptr
)
268 # Based on enum bt_clock_type in clock-type.h
276 A :class:`TraceHandle` is a handle allowing the user to manipulate
277 a specific trace directly. It is a unique identifier representing a
278 trace, and is not meant to be instantiated by the user.
282 raise NotImplementedError("TraceHandle cannot be instantiated")
285 return "Babeltrace TraceHandle: trace_id('{0}')".format(self
._id
)
290 Numeric ID of this trace handle.
298 Path of the underlying trace.
301 return nbt
._bt
_trace
_handle
_get
_path
(self
._trace
_collection
._tc
,
305 def timestamp_begin(self
):
307 Buffers creation timestamp (nanoseconds since Epoch) of the
311 ret
, value
= nbt
._bt
_trace
_handle
_get
_timestamp
_begin
(
312 self
._trace
_collection
._tc
, self
._id
, _ClockType
.CLOCK_REAL
)
314 raise ValueError("Invalid TraceHandle")
318 def timestamp_end(self
):
320 Buffers destruction timestamp (nanoseconds since Epoch) of the
324 ret
, value
= nbt
._bt
_trace
_handle
_get
_timestamp
_end
(
325 self
._trace
_collection
._tc
, self
._id
, _ClockType
.CLOCK_REAL
)
327 raise ValueError("Invalid TraceHandle")
333 Generates all the :class:`EventDeclaration` objects of the
337 ret
= nbt
._bt
_python
_event
_decl
_listcaller
(self
.id,
338 self
._trace
_collection
._tc
)
340 if not isinstance(ret
, list):
343 ptr_list
, count
= ret
345 for i
in range(count
):
346 tmp
= EventDeclaration
.__new
__(EventDeclaration
)
347 tmp
._ed
= nbt
._bt
_python
_decl
_one
_from
_list
(ptr_list
, i
)
353 # Priority of the scopes when searching for event fields
355 common
.CTFScope
.EVENT_FIELDS
,
356 common
.CTFScope
.EVENT_CONTEXT
,
357 common
.CTFScope
.STREAM_EVENT_CONTEXT
,
358 common
.CTFScope
.STREAM_EVENT_HEADER
,
359 common
.CTFScope
.STREAM_PACKET_CONTEXT
,
360 common
.CTFScope
.TRACE_PACKET_HEADER
364 class Event(collections
.Mapping
):
366 An :class:`Event` object represents a trace event. :class:`Event`
367 objects are returned by :attr:`TraceCollection.events` and are
368 not meant to be instantiated by the user.
370 :class:`Event` has a :class:`dict`-like interface for accessing
371 an event's field value by field name:
373 .. code-block:: python
377 If a field name exists in multiple scopes, the value of the first
378 field found is returned. The scopes are searched in the following
381 1. Event fields (:attr:`babeltrace.common.CTFScope.EVENT_FIELDS`)
382 2. Event context (:attr:`babeltrace.common.CTFScope.EVENT_CONTEXT`)
383 3. Stream event context (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_CONTEXT`)
384 4. Event header (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_HEADER`)
385 5. Packet context (:attr:`babeltrace.common.CTFScope.STREAM_PACKET_CONTEXT`)
386 6. Packet header (:attr:`babeltrace.common.CTFScope.TRACE_PACKET_HEADER`)
388 It is still possible to obtain a field's value from a specific
389 scope using :meth:`field_with_scope`.
391 Field values are returned as native Python types, that is:
393 +-----------------------+----------------------------------+
394 | Field type | Python type |
395 +=======================+==================================+
396 | Integer | :class:`int` |
397 +-----------------------+----------------------------------+
398 | Floating point number | :class:`float` |
399 +-----------------------+----------------------------------+
400 | Enumeration | :class:`str` (enumeration label) |
401 +-----------------------+----------------------------------+
402 | String | :class:`str` |
403 +-----------------------+----------------------------------+
404 | Array | :class:`list` of native Python |
406 +-----------------------+----------------------------------+
407 | Sequence | :class:`list` of native Python |
409 +-----------------------+----------------------------------+
410 | Structure | :class:`dict` mapping field |
411 | | names to native Python objects |
412 +-----------------------+----------------------------------+
414 For example, printing the third element of a sequence named ``seq``
415 in a structure named ``my_struct`` of the ``event``'s field named
416 ``my_field`` is done this way:
418 .. code-block:: python
420 print(event['my_field']['my_struct']['seq'][2])
424 raise NotImplementedError("Event cannot be instantiated")
429 Event name or ``None`` on error.
432 return nbt
._bt
_ctf
_event
_name
(self
._e
)
437 Event timestamp in cycles or -1 on error.
440 return nbt
._bt
_ctf
_get
_cycles
(self
._e
)
445 Event timestamp (nanoseconds since Epoch).
448 ret
, value
= nbt
._bt
_ctf
_get
_timestamp
(self
._e
)
450 raise RuntimeError("Failed to get event timestamp")
456 Event timestamp as a standard :class:`datetime.datetime`
459 Note that the :class:`datetime.datetime` class' precision
460 is limited to microseconds, whereas :attr:`timestamp` provides
461 the event's timestamp with a nanosecond resolution.
464 return datetime
.fromtimestamp(self
.timestamp
/ 1E9
)
466 def field_with_scope(self
, field_name
, scope
):
468 Returns the value of a field named *field_name* within the
469 scope *scope*, or ``None`` if the field cannot be found.
471 *scope* must be one of :class:`babeltrace.common.CTFScope`
475 if scope
not in _scopes
:
476 raise ValueError("Invalid scope provided")
478 field
= self
._field
_with
_scope
(field_name
, scope
)
480 if field
is not None:
483 def field_list_with_scope(self
, scope
):
485 Returns a list of field names in the scope *scope*.
488 if scope
not in _scopes
:
489 raise ValueError("Invalid scope provided")
493 for field
in self
._field
_list
_with
_scope
(scope
):
494 field_names
.append(field
.name
)
501 :class:`TraceHandle` object containing this event, or ``None``
505 ret
= nbt
._bt
_ctf
_event
_get
_handle
_id
(self
._e
)
510 th
= TraceHandle
.__new
__(TraceHandle
)
512 th
._trace
_collection
= self
.get_trace_collection()
517 def trace_collection(self
):
519 :class:`TraceCollection` object containing this event, or
523 trace_collection
= TraceCollection()
524 trace_collection
._tc
= nbt
._bt
_ctf
_event
_get
_context
(self
._e
)
526 if trace_collection
._tc
is not None:
527 return trace_collection
529 def __getitem__(self
, field_name
):
530 field
= self
._field
(field_name
)
532 if field
is not None:
535 raise KeyError(field_name
)
538 for key
in self
.keys():
544 for scope
in _scopes
:
545 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
546 ret
= nbt
._bt
_python
_field
_listcaller
(self
._e
, scope_ptr
)
548 if isinstance(ret
, list):
553 def __contains__(self
, field_name
):
554 return self
._field
(field_name
) is not None
558 Returns the list of field names.
560 Note: field names are unique within the returned list, although
561 a field name could exist in multiple scopes. Use
562 :meth:`field_list_with_scope` to obtain the list of field names
568 for scope
in _scopes
:
569 for name
in self
.field_list_with_scope(scope
):
570 field_names
.add(name
)
572 return list(field_names
)
574 def get(self
, field_name
, default
=None):
576 Returns the value of the field named *field_name*, or *default*
579 See :class:`Event` note about how fields are retrieved by
580 name when multiple fields share the same name in different
584 field
= self
._field
(field_name
)
593 Generates pairs of (field name, field value).
595 This method iterates :meth:`keys` to find field names, which
596 means some fields could be unavailable if other fields share
597 their names in scopes with higher priorities.
600 for field
in self
.keys():
601 yield (field
, self
[field
])
603 def _field_with_scope(self
, field_name
, scope
):
604 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
606 if scope_ptr
is None:
609 definition_ptr
= nbt
._bt
_ctf
_get
_field
(self
._e
, scope_ptr
, field_name
)
611 if definition_ptr
is None:
614 field
= _Definition(definition_ptr
, scope
)
618 def _field(self
, field_name
):
621 for scope
in _scopes
:
622 field
= self
._field
_with
_scope
(field_name
, scope
)
624 if field
is not None:
629 def _field_list_with_scope(self
, scope
):
631 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
633 # Returns a list [list_ptr, count]. If list_ptr is NULL, SWIG will only
634 # provide the "count" return value
637 ret
= nbt
._bt
_python
_field
_listcaller
(self
._e
, scope_ptr
)
639 if isinstance(ret
, list):
640 list_ptr
, count
= ret
642 for i
in range(count
):
643 definition_ptr
= nbt
._bt
_python
_field
_one
_from
_list
(list_ptr
, i
)
645 if definition_ptr
is not None:
646 definition
= _Definition(definition_ptr
, scope
)
647 fields
.append(definition
)
652 class FieldError(Exception):
654 Field error, raised when the value of a field cannot be accessed.
657 def __init__(self
, value
):
661 return repr(self
.value
)
664 class EventDeclaration
:
666 An event declaration contains the properties of a class of events,
667 that is, the common properties and fields layout of all the actual
668 recorded events associated with this declaration.
670 This class is not meant to be instantiated by the user. It is
671 returned by :attr:`TraceHandle.events`.
674 MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
677 raise NotImplementedError("EventDeclaration cannot be instantiated")
682 Event name, or ``None`` on error.
685 return nbt
._bt
_ctf
_get
_decl
_event
_name
(self
._ed
)
690 Event numeric ID, or -1 on error.
693 id = nbt
._bt
_ctf
_get
_decl
_event
_id
(self
._ed
)
695 if id == self
.MAX_UINT64
:
703 Generates all the field declarations of this event, going
704 through each scope in the following order:
706 1. Event fields (:attr:`babeltrace.common.CTFScope.EVENT_FIELDS`)
707 2. Event context (:attr:`babeltrace.common.CTFScope.EVENT_CONTEXT`)
708 3. Stream event context (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_CONTEXT`)
709 4. Event header (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_HEADER`)
710 5. Packet context (:attr:`babeltrace.common.CTFScope.STREAM_PACKET_CONTEXT`)
711 6. Packet header (:attr:`babeltrace.common.CTFScope.TRACE_PACKET_HEADER`)
713 All the generated field declarations inherit
714 :class:`FieldDeclaration`, and are among:
716 * :class:`IntegerFieldDeclaration`
717 * :class:`FloatFieldDeclaration`
718 * :class:`EnumerationFieldDeclaration`
719 * :class:`StringFieldDeclaration`
720 * :class:`ArrayFieldDeclaration`
721 * :class:`SequenceFieldDeclaration`
722 * :class:`StructureFieldDeclaration`
723 * :class:`VariantFieldDeclaration`
726 for scope
in _scopes
:
727 for declaration
in self
.fields_scope(scope
):
730 def fields_scope(self
, scope
):
732 Generates all the field declarations of the event's scope
735 *scope* must be one of :class:`babeltrace.common.CTFScope` constants.
737 All the generated field declarations inherit
738 :class:`FieldDeclaration`, and are among:
740 * :class:`IntegerFieldDeclaration`
741 * :class:`FloatFieldDeclaration`
742 * :class:`EnumerationFieldDeclaration`
743 * :class:`StringFieldDeclaration`
744 * :class:`ArrayFieldDeclaration`
745 * :class:`SequenceFieldDeclaration`
746 * :class:`StructureFieldDeclaration`
747 * :class:`VariantFieldDeclaration`
749 ret
= nbt
._by
_python
_field
_decl
_listcaller
(self
._ed
, scope
)
751 if not isinstance(ret
, list):
754 list_ptr
, count
= ret
756 for i
in range(count
):
757 field_decl_ptr
= nbt
._bt
_python
_field
_decl
_one
_from
_list
(list_ptr
, i
)
759 if field_decl_ptr
is not None:
760 decl_ptr
= nbt
._bt
_ctf
_get
_decl
_from
_field
_decl
(field_decl_ptr
)
761 name
= nbt
._bt
_ctf
_get
_decl
_field
_name
(field_decl_ptr
)
762 field_declaration
= _create_field_declaration(decl_ptr
, name
,
764 yield field_declaration
767 class FieldDeclaration
:
769 Base class for concrete field declarations.
771 This class is not meant to be instantiated by the user.
775 raise NotImplementedError("FieldDeclaration cannot be instantiated")
778 return "({0}) {1} {2}".format(common
.CTFScope
.scope_name(self
.scope
),
779 common
.CTFTypeId
.type_name(self
.type),
785 Field name, or ``None`` on error.
793 Field type (one of :class:`babeltrace.common.CTFTypeId`
797 return nbt
._bt
_ctf
_field
_type
(self
._fd
)
802 Field scope (one of:class:`babeltrace.common.CTFScope`
809 class IntegerFieldDeclaration(FieldDeclaration
):
811 Integer field declaration.
815 raise NotImplementedError("IntegerFieldDeclaration cannot be instantiated")
818 def signedness(self
):
820 0 if this integer is unsigned, 1 if signed, or -1 on error.
823 return nbt
._bt
_ctf
_get
_int
_signedness
(self
._fd
)
828 Integer base (:class:`int`), or a negative value on error.
831 return nbt
._bt
_ctf
_get
_int
_base
(self
._fd
)
834 def byte_order(self
):
836 Integer byte order (one of
837 :class:`babeltrace.common.ByteOrder` constants).
840 ret
= nbt
._bt
_ctf
_get
_int
_byte
_order
(self
._fd
)
843 return common
.ByteOrder
.BYTE_ORDER_LITTLE_ENDIAN
845 return common
.ByteOrder
.BYTE_ORDER_BIG_ENDIAN
847 return common
.ByteOrder
.BYTE_ORDER_UNKNOWN
852 Integer size in bits, or a negative value on error.
854 return nbt
._bt
_ctf
_get
_int
_len
(self
._fd
)
863 Integer encoding (one of
864 :class:`babeltrace.common.CTFStringEncoding` constants).
867 return nbt
._bt
_ctf
_get
_encoding
(self
._fd
)
870 class EnumerationFieldDeclaration(FieldDeclaration
):
872 Enumeration field declaration.
876 As of this version, this class is missing some properties.
880 raise NotImplementedError("EnumerationFieldDeclaration cannot be instantiated")
883 class ArrayFieldDeclaration(FieldDeclaration
):
885 Static array field declaration.
889 raise NotImplementedError("ArrayFieldDeclaration cannot be instantiated")
894 Fixed length of this static array (number of contained
895 elements), or a negative value on error.
898 return nbt
._bt
_ctf
_get
_array
_len
(self
._fd
)
901 def element_declaration(self
):
903 Field declaration of the underlying element.
906 field_decl_ptr
= nbt
._bt
_python
_get
_array
_element
_declaration
(self
._fd
)
908 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
911 class SequenceFieldDeclaration(FieldDeclaration
):
913 Sequence (dynamic array) field declaration.
917 As of this version, this class is missing some properties.
921 raise NotImplementedError("SequenceFieldDeclaration cannot be instantiated")
924 def element_declaration(self
):
926 Field declaration of the underlying element.
929 field_decl_ptr
= nbt
._bt
_python
_get
_sequence
_element
_declaration
(self
._fd
)
931 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
934 class FloatFieldDeclaration(FieldDeclaration
):
936 Floating point number field declaration.
940 As of this version, this class is missing some properties.
944 raise NotImplementedError("FloatFieldDeclaration cannot be instantiated")
947 class StructureFieldDeclaration(FieldDeclaration
):
949 Structure (ordered map of field names to field declarations) field
954 As of this version, this class is missing some properties.
958 raise NotImplementedError("StructureFieldDeclaration cannot be instantiated")
961 class StringFieldDeclaration(FieldDeclaration
):
963 String (NULL-terminated array of bytes) field declaration.
967 As of this version, this class is missing some properties.
971 raise NotImplementedError("StringFieldDeclaration cannot be instantiated")
974 class VariantFieldDeclaration(FieldDeclaration
):
976 Variant (dynamic selection between different types) field declaration.
980 As of this version, this class is missing some properties.
984 raise NotImplementedError("VariantFieldDeclaration cannot be instantiated")
989 Return the last error code encountered while
990 accessing a field and reset the error flag.
991 Return 0 if no error, a negative value otherwise.
994 return nbt
._bt
_ctf
_field
_get
_error
()
997 def _create_field_declaration(declaration_ptr
, name
, scope
):
999 Private field declaration factory.
1002 if declaration_ptr
is None:
1003 raise ValueError("declaration_ptr must be valid")
1004 if scope
not in _scopes
:
1005 raise ValueError("Invalid scope provided")
1007 type = nbt
._bt
_ctf
_field
_type
(declaration_ptr
)
1010 if type == common
.CTFTypeId
.INTEGER
:
1011 declaration
= IntegerFieldDeclaration
.__new
__(IntegerFieldDeclaration
)
1012 elif type == common
.CTFTypeId
.ENUM
:
1013 declaration
= EnumerationFieldDeclaration
.__new
__(EnumerationFieldDeclaration
)
1014 elif type == common
.CTFTypeId
.ARRAY
:
1015 declaration
= ArrayFieldDeclaration
.__new
__(ArrayFieldDeclaration
)
1016 elif type == common
.CTFTypeId
.SEQUENCE
:
1017 declaration
= SequenceFieldDeclaration
.__new
__(SequenceFieldDeclaration
)
1018 elif type == common
.CTFTypeId
.FLOAT
:
1019 declaration
= FloatFieldDeclaration
.__new
__(FloatFieldDeclaration
)
1020 elif type == common
.CTFTypeId
.STRUCT
:
1021 declaration
= StructureFieldDeclaration
.__new
__(StructureFieldDeclaration
)
1022 elif type == common
.CTFTypeId
.STRING
:
1023 declaration
= StringFieldDeclaration
.__new
__(StringFieldDeclaration
)
1024 elif type == common
.CTFTypeId
.VARIANT
:
1025 declaration
= VariantFieldDeclaration
.__new
__(VariantFieldDeclaration
)
1029 declaration
._fd
= declaration_ptr
1030 declaration
._s
= scope
1031 declaration
._name
= name
1037 def __init__(self
, definition_ptr
, scope
):
1038 self
._d
= definition_ptr
1041 if scope
not in _scopes
:
1042 ValueError("Invalid scope provided")
1046 """Return the name of a field or None on error."""
1048 return nbt
._bt
_ctf
_field
_name
(self
._d
)
1052 """Return the type of a field or -1 if unknown."""
1054 return nbt
._bt
_ctf
_field
_type
(nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
))
1057 def declaration(self
):
1058 """Return the associated Definition object."""
1060 return _create_field_declaration(
1061 nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
), self
.name
, self
.scope
)
1063 def _get_enum_str(self
):
1065 Return the string matching the current enumeration.
1066 Return None on error.
1069 return nbt
._bt
_ctf
_get
_enum
_str
(self
._d
)
1071 def _get_array_element_at(self
, index
):
1073 Return the array's element at position index.
1074 Return None on error
1077 array_ptr
= nbt
._bt
_python
_get
_array
_from
_def
(self
._d
)
1079 if array_ptr
is None:
1082 definition_ptr
= nbt
._bt
_array
_index
(array_ptr
, index
)
1084 if definition_ptr
is None:
1087 return _Definition(definition_ptr
, self
.scope
)
1089 def _get_sequence_len(self
):
1091 Return the len of a sequence or a negative
1095 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
1097 return nbt
._bt
_sequence
_len
(seq
)
1099 def _get_sequence_element_at(self
, index
):
1101 Return the sequence's element at position index,
1102 otherwise return None
1105 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
1108 definition_ptr
= nbt
._bt
_sequence
_index
(seq
, index
)
1110 if definition_ptr
is not None:
1111 return _Definition(definition_ptr
, self
.scope
)
1113 def _get_uint64(self
):
1115 Return the value associated with the field.
1116 If the field does not exist or is not of the type requested,
1117 the value returned is undefined. To check if an error occured,
1118 use the field_error() function after accessing a field.
1121 return nbt
._bt
_ctf
_get
_uint
64(self
._d
)
1123 def _get_int64(self
):
1125 Return the value associated with the field.
1126 If the field does not exist or is not of the type requested,
1127 the value returned is undefined. To check if an error occured,
1128 use the field_error() function after accessing a field.
1131 return nbt
._bt
_ctf
_get
_int
64(self
._d
)
1133 def _get_char_array(self
):
1135 Return the value associated with the field.
1136 If the field does not exist or is not of the type requested,
1137 the value returned is undefined. To check if an error occurred,
1138 use the field_error() function after accessing a field.
1141 return nbt
._bt
_ctf
_get
_char
_array
(self
._d
)
1145 Return the value associated with the field.
1146 If the field does not exist or is not of the type requested,
1147 the value returned is undefined. To check if an error occurred,
1148 use the field_error() function after accessing a field.
1151 return nbt
._bt
_ctf
_get
_string
(self
._d
)
1153 def _get_float(self
):
1155 Return the value associated with the field.
1156 If the field does not exist or is not of the type requested,
1157 the value returned is undefined. To check if an error occurred,
1158 use the field_error() function after accessing a field.
1161 return nbt
._bt
_ctf
_get
_float
(self
._d
)
1163 def _get_variant(self
):
1165 Return the variant's selected field.
1166 If the field does not exist or is not of the type requested,
1167 the value returned is undefined. To check if an error occurred,
1168 use the field_error() function after accessing a field.
1171 return nbt
._bt
_ctf
_get
_variant
(self
._d
)
1173 def _get_struct_field_count(self
):
1175 Return the number of fields contained in the structure.
1176 If the field does not exist or is not of the type requested,
1177 the value returned is undefined.
1180 return nbt
._bt
_ctf
_get
_struct
_field
_count
(self
._d
)
1182 def _get_struct_field_at(self
, i
):
1184 Return the structure's field at position i.
1185 If the field does not exist or is not of the type requested,
1186 the value returned is undefined. To check if an error occurred,
1187 use the field_error() function after accessing a field.
1190 return nbt
._bt
_ctf
_get
_struct
_field
_index
(self
._d
, i
)
1195 Return the value associated with the field according to its type.
1196 Return None on error.
1202 if id == common
.CTFTypeId
.STRING
:
1203 value
= self
._get
_str
()
1204 elif id == common
.CTFTypeId
.ARRAY
:
1205 element_decl
= self
.declaration
.element_declaration
1207 if ((element_decl
.type == common
.CTFTypeId
.INTEGER
1208 and element_decl
.length
== 8)
1209 and (element_decl
.encoding
== common
.CTFStringEncoding
.ASCII
or element_decl
.encoding
== common
.CTFStringEncoding
.UTF8
)):
1210 value
= nbt
._bt
_python
_get
_array
_string
(self
._d
)
1214 for i
in range(self
.declaration
.length
):
1215 element
= self
._get
_array
_element
_at
(i
)
1216 value
.append(element
.value
)
1217 elif id == common
.CTFTypeId
.INTEGER
:
1218 if self
.declaration
.signedness
== 0:
1219 value
= self
._get
_uint
64()
1221 value
= self
._get
_int
64()
1222 elif id == common
.CTFTypeId
.ENUM
:
1223 value
= self
._get
_enum
_str
()
1224 elif id == common
.CTFTypeId
.SEQUENCE
:
1225 element_decl
= self
.declaration
.element_declaration
1227 if ((element_decl
.type == common
.CTFTypeId
.INTEGER
1228 and element_decl
.length
== 8)
1229 and (element_decl
.encoding
== common
.CTFStringEncoding
.ASCII
or element_decl
.encoding
== common
.CTFStringEncoding
.UTF8
)):
1230 value
= nbt
._bt
_python
_get
_sequence
_string
(self
._d
)
1232 seq_len
= self
._get
_sequence
_len
()
1235 for i
in range(seq_len
):
1236 evDef
= self
._get
_sequence
_element
_at
(i
)
1237 value
.append(evDef
.value
)
1238 elif id == common
.CTFTypeId
.FLOAT
:
1239 value
= self
._get
_float
()
1240 elif id == common
.CTFTypeId
.VARIANT
:
1241 variant
= _Definition
.__new
__(_Definition
)
1242 variant
._d
= self
._get
_variant
()
1243 value
= variant
.value
1244 elif id == common
.CTFTypeId
.STRUCT
:
1247 for i
in range(self
._get
_struct
_field
_count
()):
1248 member
= _Definition(self
._get
_struct
_field
_at
(i
), self
.scope
)
1249 value
[member
.name
] = member
.value
1253 "Error occurred while accessing field {} of type {}".format(
1255 common
.CTFTypeId
.type_name(id)))
1261 """Return the scope of a field or None on error."""