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
141 def has_intersection(self
):
142 return nbt
._bt
_python
_has
_intersection
(self
._tc
)
147 Generates the ordered :class:`Event` objects of all the opened
148 traces contained in this trace collection.
150 Due to limitations of the native Babeltrace API, only one event
151 may be "alive" at a given time, i.e. a user **should never**
152 store a copy of the events returned by this function for
153 ulterior use. Users shall make sure to copy the information
154 they need *from* an event before accessing the next one.
157 begin_pos_ptr
= nbt
._bt
_python
_create
_iter
_pos
()
158 end_pos_ptr
= nbt
._bt
_python
_create
_iter
_pos
()
160 if not self
.intersect_mode
:
161 begin_pos_ptr
.type = nbt
.SEEK_BEGIN
162 end_pos_ptr
.type = nbt
.SEEK_LAST
164 for event
in self
._events
(begin_pos_ptr
, end_pos_ptr
):
167 nbt
._bt
_iter
_free
_pos
(begin_pos_ptr
)
168 nbt
._bt
_iter
_free
_pos
(end_pos_ptr
)
170 def events_timestamps(self
, timestamp_begin
, timestamp_end
):
172 Generates the ordered :class:`Event` objects of all the opened
173 traces contained in this trace collection from *timestamp_begin*
176 *timestamp_begin* and *timestamp_end* are given in nanoseconds
179 See :attr:`events` for notes and limitations.
182 begin_pos_ptr
= nbt
._bt
_python
_create
_iter
_pos
()
183 end_pos_ptr
= nbt
._bt
_python
_create
_iter
_pos
()
184 begin_pos_ptr
.type = end_pos_ptr
.type = nbt
.SEEK_TIME
185 begin_pos_ptr
.u
.seek_time
= timestamp_begin
186 end_pos_ptr
.u
.seek_time
= timestamp_end
188 for event
in self
._events
(begin_pos_ptr
, end_pos_ptr
):
191 nbt
._bt
_iter
_free
_pos
(begin_pos_ptr
)
192 nbt
._bt
_iter
_free
_pos
(end_pos_ptr
)
195 def timestamp_begin(self
):
197 Begin timestamp of this trace collection (nanoseconds since
201 pos_ptr
= nbt
._bt
_iter
_pos
()
202 pos_ptr
.type = nbt
.SEEK_BEGIN
204 return self
._timestamp
_at
_pos
(pos_ptr
)
207 def timestamp_end(self
):
209 End timestamp of this trace collection (nanoseconds since
213 pos_ptr
= nbt
._bt
_iter
_pos
()
214 pos_ptr
.type = nbt
.SEEK_LAST
216 return self
._timestamp
_at
_pos
(pos_ptr
)
218 def _timestamp_at_pos(self
, pos_ptr
):
219 ctf_it_ptr
= nbt
._bt
_ctf
_iter
_create
(self
._tc
, pos_ptr
, pos_ptr
)
221 if ctf_it_ptr
is None:
222 raise NotImplementedError("Creation of multiple iterators is unsupported.")
224 ev_ptr
= nbt
._bt
_ctf
_iter
_read
_event
(ctf_it_ptr
)
225 nbt
._bt
_ctf
_iter
_destroy
(ctf_it_ptr
)
227 ev
= Event
.__new
__(Event
)
232 def _events(self
, begin_pos_ptr
, end_pos_ptr
):
233 if self
.intersect_mode
:
234 if not self
.has_intersection
:
235 # There are no events to provide.
238 ctf_it_ptr
= nbt
._bt
_python
_ctf
_iter
_create
_intersect
(
239 self
._tc
, begin_pos_ptr
, end_pos_ptr
242 ctf_it_ptr
= nbt
._bt
_ctf
_iter
_create
(
243 self
._tc
, begin_pos_ptr
, end_pos_ptr
246 if ctf_it_ptr
is None:
247 raise NotImplementedError("Creation of multiple iterators is unsupported.")
250 ev_ptr
= nbt
._bt
_ctf
_iter
_read
_event
(ctf_it_ptr
)
255 ev
= Event
.__new
__(Event
)
260 except GeneratorExit
:
263 ret
= nbt
._bt
_iter
_next
(nbt
._bt
_ctf
_get
_iter
(ctf_it_ptr
))
268 nbt
._bt
_ctf
_iter
_destroy
(ctf_it_ptr
)
271 # Based on enum bt_clock_type in clock-type.h
279 A :class:`TraceHandle` is a handle allowing the user to manipulate
280 a specific trace directly. It is a unique identifier representing a
281 trace, and is not meant to be instantiated by the user.
285 raise NotImplementedError("TraceHandle cannot be instantiated")
288 return "Babeltrace TraceHandle: trace_id('{0}')".format(self
._id
)
293 Numeric ID of this trace handle.
301 Path of the underlying trace.
304 return nbt
._bt
_trace
_handle
_get
_path
(self
._trace
_collection
._tc
,
308 def timestamp_begin(self
):
310 Buffers creation timestamp (nanoseconds since Epoch) of the
314 ret
, value
= nbt
._bt
_trace
_handle
_get
_timestamp
_begin
(
315 self
._trace
_collection
._tc
, self
._id
, _ClockType
.CLOCK_REAL
)
317 raise ValueError("Invalid TraceHandle")
321 def timestamp_end(self
):
323 Buffers destruction timestamp (nanoseconds since Epoch) of the
327 ret
, value
= nbt
._bt
_trace
_handle
_get
_timestamp
_end
(
328 self
._trace
_collection
._tc
, self
._id
, _ClockType
.CLOCK_REAL
)
330 raise ValueError("Invalid TraceHandle")
336 Generates all the :class:`EventDeclaration` objects of the
340 ret
= nbt
._bt
_python
_event
_decl
_listcaller
(self
.id,
341 self
._trace
_collection
._tc
)
343 if not isinstance(ret
, list):
346 ptr_list
, count
= ret
348 for i
in range(count
):
349 tmp
= EventDeclaration
.__new
__(EventDeclaration
)
350 tmp
._ed
= nbt
._bt
_python
_decl
_one
_from
_list
(ptr_list
, i
)
356 # Priority of the scopes when searching for event fields
358 common
.CTFScope
.EVENT_FIELDS
,
359 common
.CTFScope
.EVENT_CONTEXT
,
360 common
.CTFScope
.STREAM_EVENT_CONTEXT
,
361 common
.CTFScope
.STREAM_EVENT_HEADER
,
362 common
.CTFScope
.STREAM_PACKET_CONTEXT
,
363 common
.CTFScope
.TRACE_PACKET_HEADER
367 class Event(collections
.Mapping
):
369 An :class:`Event` object represents a trace event. :class:`Event`
370 objects are returned by :attr:`TraceCollection.events` and are
371 not meant to be instantiated by the user.
373 :class:`Event` has a :class:`dict`-like interface for accessing
374 an event's field value by field name:
376 .. code-block:: python
380 If a field name exists in multiple scopes, the value of the first
381 field found is returned. The scopes are searched in the following
384 1. Event fields (:attr:`babeltrace.common.CTFScope.EVENT_FIELDS`)
385 2. Event context (:attr:`babeltrace.common.CTFScope.EVENT_CONTEXT`)
386 3. Stream event context (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_CONTEXT`)
387 4. Event header (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_HEADER`)
388 5. Packet context (:attr:`babeltrace.common.CTFScope.STREAM_PACKET_CONTEXT`)
389 6. Packet header (:attr:`babeltrace.common.CTFScope.TRACE_PACKET_HEADER`)
391 It is still possible to obtain a field's value from a specific
392 scope using :meth:`field_with_scope`.
394 Field values are returned as native Python types, that is:
396 +-----------------------+----------------------------------+
397 | Field type | Python type |
398 +=======================+==================================+
399 | Integer | :class:`int` |
400 +-----------------------+----------------------------------+
401 | Floating point number | :class:`float` |
402 +-----------------------+----------------------------------+
403 | Enumeration | :class:`str` (enumeration label) |
404 +-----------------------+----------------------------------+
405 | String | :class:`str` |
406 +-----------------------+----------------------------------+
407 | Array | :class:`list` of native Python |
409 +-----------------------+----------------------------------+
410 | Sequence | :class:`list` of native Python |
412 +-----------------------+----------------------------------+
413 | Structure | :class:`dict` mapping field |
414 | | names to native Python objects |
415 +-----------------------+----------------------------------+
417 For example, printing the third element of a sequence named ``seq``
418 in a structure named ``my_struct`` of the ``event``'s field named
419 ``my_field`` is done this way:
421 .. code-block:: python
423 print(event['my_field']['my_struct']['seq'][2])
427 raise NotImplementedError("Event cannot be instantiated")
432 Event name or ``None`` on error.
435 return nbt
._bt
_ctf
_event
_name
(self
._e
)
440 Event timestamp in cycles or -1 on error.
443 return nbt
._bt
_ctf
_get
_cycles
(self
._e
)
448 Event timestamp (nanoseconds since Epoch).
451 ret
, value
= nbt
._bt
_ctf
_get
_timestamp
(self
._e
)
453 raise RuntimeError("Failed to get event timestamp")
459 Event timestamp as a standard :class:`datetime.datetime`
462 Note that the :class:`datetime.datetime` class' precision
463 is limited to microseconds, whereas :attr:`timestamp` provides
464 the event's timestamp with a nanosecond resolution.
467 return datetime
.fromtimestamp(self
.timestamp
/ 1E9
)
469 def field_with_scope(self
, field_name
, scope
):
471 Returns the value of a field named *field_name* within the
472 scope *scope*, or ``None`` if the field cannot be found.
474 *scope* must be one of :class:`babeltrace.common.CTFScope`
478 if scope
not in _scopes
:
479 raise ValueError("Invalid scope provided")
481 field
= self
._field
_with
_scope
(field_name
, scope
)
483 if field
is not None:
486 def field_list_with_scope(self
, scope
):
488 Returns a list of field names in the scope *scope*.
491 if scope
not in _scopes
:
492 raise ValueError("Invalid scope provided")
496 for field
in self
._field
_list
_with
_scope
(scope
):
497 field_names
.append(field
.name
)
504 :class:`TraceHandle` object containing this event, or ``None``
508 ret
= nbt
._bt
_ctf
_event
_get
_handle
_id
(self
._e
)
513 th
= TraceHandle
.__new
__(TraceHandle
)
515 th
._trace
_collection
= self
.get_trace_collection()
520 def trace_collection(self
):
522 :class:`TraceCollection` object containing this event, or
526 trace_collection
= TraceCollection()
527 trace_collection
._tc
= nbt
._bt
_ctf
_event
_get
_context
(self
._e
)
529 if trace_collection
._tc
is not None:
530 return trace_collection
532 def __getitem__(self
, field_name
):
533 field
= self
._field
(field_name
)
535 if field
is not None:
538 raise KeyError(field_name
)
541 for key
in self
.keys():
547 for scope
in _scopes
:
548 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
549 ret
= nbt
._bt
_python
_field
_listcaller
(self
._e
, scope_ptr
)
551 if isinstance(ret
, list):
556 def __contains__(self
, field_name
):
557 return self
._field
(field_name
) is not None
561 Returns the list of field names.
563 Note: field names are unique within the returned list, although
564 a field name could exist in multiple scopes. Use
565 :meth:`field_list_with_scope` to obtain the list of field names
571 for scope
in _scopes
:
572 for name
in self
.field_list_with_scope(scope
):
573 field_names
.add(name
)
575 return list(field_names
)
577 def get(self
, field_name
, default
=None):
579 Returns the value of the field named *field_name*, or *default*
582 See :class:`Event` note about how fields are retrieved by
583 name when multiple fields share the same name in different
587 field
= self
._field
(field_name
)
596 Generates pairs of (field name, field value).
598 This method iterates :meth:`keys` to find field names, which
599 means some fields could be unavailable if other fields share
600 their names in scopes with higher priorities.
603 for field
in self
.keys():
604 yield (field
, self
[field
])
606 def _field_with_scope(self
, field_name
, scope
):
607 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
609 if scope_ptr
is None:
612 definition_ptr
= nbt
._bt
_ctf
_get
_field
(self
._e
, scope_ptr
, field_name
)
614 if definition_ptr
is None:
617 field
= _Definition(definition_ptr
, scope
)
621 def _field(self
, field_name
):
624 for scope
in _scopes
:
625 field
= self
._field
_with
_scope
(field_name
, scope
)
627 if field
is not None:
632 def _field_list_with_scope(self
, scope
):
634 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
636 # Returns a list [list_ptr, count]. If list_ptr is NULL, SWIG will only
637 # provide the "count" return value
640 ret
= nbt
._bt
_python
_field
_listcaller
(self
._e
, scope_ptr
)
642 if isinstance(ret
, list):
643 list_ptr
, count
= ret
645 for i
in range(count
):
646 definition_ptr
= nbt
._bt
_python
_field
_one
_from
_list
(list_ptr
, i
)
648 if definition_ptr
is not None:
649 definition
= _Definition(definition_ptr
, scope
)
650 fields
.append(definition
)
655 class FieldError(Exception):
657 Field error, raised when the value of a field cannot be accessed.
660 def __init__(self
, value
):
664 return repr(self
.value
)
667 class EventDeclaration
:
669 An event declaration contains the properties of a class of events,
670 that is, the common properties and fields layout of all the actual
671 recorded events associated with this declaration.
673 This class is not meant to be instantiated by the user. It is
674 returned by :attr:`TraceHandle.events`.
677 MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
680 raise NotImplementedError("EventDeclaration cannot be instantiated")
685 Event name, or ``None`` on error.
688 return nbt
._bt
_ctf
_get
_decl
_event
_name
(self
._ed
)
693 Event numeric ID, or -1 on error.
696 id = nbt
._bt
_ctf
_get
_decl
_event
_id
(self
._ed
)
698 if id == self
.MAX_UINT64
:
706 Generates all the field declarations of this event, going
707 through each scope in the following order:
709 1. Event fields (:attr:`babeltrace.common.CTFScope.EVENT_FIELDS`)
710 2. Event context (:attr:`babeltrace.common.CTFScope.EVENT_CONTEXT`)
711 3. Stream event context (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_CONTEXT`)
712 4. Event header (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_HEADER`)
713 5. Packet context (:attr:`babeltrace.common.CTFScope.STREAM_PACKET_CONTEXT`)
714 6. Packet header (:attr:`babeltrace.common.CTFScope.TRACE_PACKET_HEADER`)
716 All the generated field declarations inherit
717 :class:`FieldDeclaration`, and are among:
719 * :class:`IntegerFieldDeclaration`
720 * :class:`FloatFieldDeclaration`
721 * :class:`EnumerationFieldDeclaration`
722 * :class:`StringFieldDeclaration`
723 * :class:`ArrayFieldDeclaration`
724 * :class:`SequenceFieldDeclaration`
725 * :class:`StructureFieldDeclaration`
726 * :class:`VariantFieldDeclaration`
729 for scope
in _scopes
:
730 for declaration
in self
.fields_scope(scope
):
733 def fields_scope(self
, scope
):
735 Generates all the field declarations of the event's scope
738 *scope* must be one of :class:`babeltrace.common.CTFScope` constants.
740 All the generated field declarations inherit
741 :class:`FieldDeclaration`, and are among:
743 * :class:`IntegerFieldDeclaration`
744 * :class:`FloatFieldDeclaration`
745 * :class:`EnumerationFieldDeclaration`
746 * :class:`StringFieldDeclaration`
747 * :class:`ArrayFieldDeclaration`
748 * :class:`SequenceFieldDeclaration`
749 * :class:`StructureFieldDeclaration`
750 * :class:`VariantFieldDeclaration`
752 ret
= nbt
._by
_python
_field
_decl
_listcaller
(self
._ed
, scope
)
754 if not isinstance(ret
, list):
757 list_ptr
, count
= ret
759 for i
in range(count
):
760 field_decl_ptr
= nbt
._bt
_python
_field
_decl
_one
_from
_list
(list_ptr
, i
)
762 if field_decl_ptr
is not None:
763 decl_ptr
= nbt
._bt
_ctf
_get
_decl
_from
_field
_decl
(field_decl_ptr
)
764 name
= nbt
._bt
_ctf
_get
_decl
_field
_name
(field_decl_ptr
)
765 field_declaration
= _create_field_declaration(decl_ptr
, name
,
767 yield field_declaration
770 class FieldDeclaration
:
772 Base class for concrete field declarations.
774 This class is not meant to be instantiated by the user.
778 raise NotImplementedError("FieldDeclaration cannot be instantiated")
781 return "({0}) {1} {2}".format(common
.CTFScope
.scope_name(self
.scope
),
782 common
.CTFTypeId
.type_name(self
.type),
788 Field name, or ``None`` on error.
796 Field type (one of :class:`babeltrace.common.CTFTypeId`
800 return nbt
._bt
_ctf
_field
_type
(self
._fd
)
805 Field scope (one of:class:`babeltrace.common.CTFScope`
812 class IntegerFieldDeclaration(FieldDeclaration
):
814 Integer field declaration.
818 raise NotImplementedError("IntegerFieldDeclaration cannot be instantiated")
821 def signedness(self
):
823 0 if this integer is unsigned, 1 if signed, or -1 on error.
826 return nbt
._bt
_ctf
_get
_int
_signedness
(self
._fd
)
831 Integer base (:class:`int`), or a negative value on error.
834 return nbt
._bt
_ctf
_get
_int
_base
(self
._fd
)
837 def byte_order(self
):
839 Integer byte order (one of
840 :class:`babeltrace.common.ByteOrder` constants).
843 ret
= nbt
._bt
_ctf
_get
_int
_byte
_order
(self
._fd
)
846 return common
.ByteOrder
.BYTE_ORDER_LITTLE_ENDIAN
848 return common
.ByteOrder
.BYTE_ORDER_BIG_ENDIAN
850 return common
.ByteOrder
.BYTE_ORDER_UNKNOWN
855 Integer size in bits, or a negative value on error.
857 return nbt
._bt
_ctf
_get
_int
_len
(self
._fd
)
866 Integer encoding (one of
867 :class:`babeltrace.common.CTFStringEncoding` constants).
870 return nbt
._bt
_ctf
_get
_encoding
(self
._fd
)
873 class EnumerationFieldDeclaration(FieldDeclaration
):
875 Enumeration field declaration.
879 As of this version, this class is missing some properties.
883 raise NotImplementedError("EnumerationFieldDeclaration cannot be instantiated")
886 class ArrayFieldDeclaration(FieldDeclaration
):
888 Static array field declaration.
892 raise NotImplementedError("ArrayFieldDeclaration cannot be instantiated")
897 Fixed length of this static array (number of contained
898 elements), or a negative value on error.
901 return nbt
._bt
_ctf
_get
_array
_len
(self
._fd
)
904 def element_declaration(self
):
906 Field declaration of the underlying element.
909 field_decl_ptr
= nbt
._bt
_python
_get
_array
_element
_declaration
(self
._fd
)
911 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
914 class SequenceFieldDeclaration(FieldDeclaration
):
916 Sequence (dynamic array) field declaration.
920 As of this version, this class is missing some properties.
924 raise NotImplementedError("SequenceFieldDeclaration cannot be instantiated")
927 def element_declaration(self
):
929 Field declaration of the underlying element.
932 field_decl_ptr
= nbt
._bt
_python
_get
_sequence
_element
_declaration
(self
._fd
)
934 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
937 class FloatFieldDeclaration(FieldDeclaration
):
939 Floating point number field declaration.
943 As of this version, this class is missing some properties.
947 raise NotImplementedError("FloatFieldDeclaration cannot be instantiated")
950 class StructureFieldDeclaration(FieldDeclaration
):
952 Structure (ordered map of field names to field declarations) field
957 As of this version, this class is missing some properties.
961 raise NotImplementedError("StructureFieldDeclaration cannot be instantiated")
964 class StringFieldDeclaration(FieldDeclaration
):
966 String (NULL-terminated array of bytes) field declaration.
970 As of this version, this class is missing some properties.
974 raise NotImplementedError("StringFieldDeclaration cannot be instantiated")
977 class VariantFieldDeclaration(FieldDeclaration
):
979 Variant (dynamic selection between different types) field declaration.
983 As of this version, this class is missing some properties.
987 raise NotImplementedError("VariantFieldDeclaration cannot be instantiated")
992 Return the last error code encountered while
993 accessing a field and reset the error flag.
994 Return 0 if no error, a negative value otherwise.
997 return nbt
._bt
_ctf
_field
_get
_error
()
1000 def _create_field_declaration(declaration_ptr
, name
, scope
):
1002 Private field declaration factory.
1005 if declaration_ptr
is None:
1006 raise ValueError("declaration_ptr must be valid")
1007 if scope
not in _scopes
:
1008 raise ValueError("Invalid scope provided")
1010 type = nbt
._bt
_ctf
_field
_type
(declaration_ptr
)
1013 if type == common
.CTFTypeId
.INTEGER
:
1014 declaration
= IntegerFieldDeclaration
.__new
__(IntegerFieldDeclaration
)
1015 elif type == common
.CTFTypeId
.ENUM
:
1016 declaration
= EnumerationFieldDeclaration
.__new
__(EnumerationFieldDeclaration
)
1017 elif type == common
.CTFTypeId
.ARRAY
:
1018 declaration
= ArrayFieldDeclaration
.__new
__(ArrayFieldDeclaration
)
1019 elif type == common
.CTFTypeId
.SEQUENCE
:
1020 declaration
= SequenceFieldDeclaration
.__new
__(SequenceFieldDeclaration
)
1021 elif type == common
.CTFTypeId
.FLOAT
:
1022 declaration
= FloatFieldDeclaration
.__new
__(FloatFieldDeclaration
)
1023 elif type == common
.CTFTypeId
.STRUCT
:
1024 declaration
= StructureFieldDeclaration
.__new
__(StructureFieldDeclaration
)
1025 elif type == common
.CTFTypeId
.STRING
:
1026 declaration
= StringFieldDeclaration
.__new
__(StringFieldDeclaration
)
1027 elif type == common
.CTFTypeId
.VARIANT
:
1028 declaration
= VariantFieldDeclaration
.__new
__(VariantFieldDeclaration
)
1032 declaration
._fd
= declaration_ptr
1033 declaration
._s
= scope
1034 declaration
._name
= name
1040 def __init__(self
, definition_ptr
, scope
):
1041 self
._d
= definition_ptr
1044 if scope
not in _scopes
:
1045 ValueError("Invalid scope provided")
1049 """Return the name of a field or None on error."""
1051 return nbt
._bt
_ctf
_field
_name
(self
._d
)
1055 """Return the type of a field or -1 if unknown."""
1057 return nbt
._bt
_ctf
_field
_type
(nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
))
1060 def declaration(self
):
1061 """Return the associated Definition object."""
1063 return _create_field_declaration(
1064 nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
), self
.name
, self
.scope
)
1066 def _get_enum_str(self
):
1068 Return the string matching the current enumeration.
1069 Return None on error.
1072 return nbt
._bt
_ctf
_get
_enum
_str
(self
._d
)
1074 def _get_array_element_at(self
, index
):
1076 Return the array's element at position index.
1077 Return None on error
1080 array_ptr
= nbt
._bt
_python
_get
_array
_from
_def
(self
._d
)
1082 if array_ptr
is None:
1085 definition_ptr
= nbt
._bt
_array
_index
(array_ptr
, index
)
1087 if definition_ptr
is None:
1090 return _Definition(definition_ptr
, self
.scope
)
1092 def _get_sequence_len(self
):
1094 Return the len of a sequence or a negative
1098 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
1100 return nbt
._bt
_sequence
_len
(seq
)
1102 def _get_sequence_element_at(self
, index
):
1104 Return the sequence's element at position index,
1105 otherwise return None
1108 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
1111 definition_ptr
= nbt
._bt
_sequence
_index
(seq
, index
)
1113 if definition_ptr
is not None:
1114 return _Definition(definition_ptr
, self
.scope
)
1116 def _get_uint64(self
):
1118 Return the value associated with the field.
1119 If the field does not exist or is not of the type requested,
1120 the value returned is undefined. To check if an error occured,
1121 use the field_error() function after accessing a field.
1124 return nbt
._bt
_ctf
_get
_uint
64(self
._d
)
1126 def _get_int64(self
):
1128 Return the value associated with the field.
1129 If the field does not exist or is not of the type requested,
1130 the value returned is undefined. To check if an error occured,
1131 use the field_error() function after accessing a field.
1134 return nbt
._bt
_ctf
_get
_int
64(self
._d
)
1136 def _get_char_array(self
):
1138 Return the value associated with the field.
1139 If the field does not exist or is not of the type requested,
1140 the value returned is undefined. To check if an error occurred,
1141 use the field_error() function after accessing a field.
1144 return nbt
._bt
_ctf
_get
_char
_array
(self
._d
)
1148 Return the value associated with the field.
1149 If the field does not exist or is not of the type requested,
1150 the value returned is undefined. To check if an error occurred,
1151 use the field_error() function after accessing a field.
1154 return nbt
._bt
_ctf
_get
_string
(self
._d
)
1156 def _get_float(self
):
1158 Return the value associated with the field.
1159 If the field does not exist or is not of the type requested,
1160 the value returned is undefined. To check if an error occurred,
1161 use the field_error() function after accessing a field.
1164 return nbt
._bt
_ctf
_get
_float
(self
._d
)
1166 def _get_variant(self
):
1168 Return the variant's selected field.
1169 If the field does not exist or is not of the type requested,
1170 the value returned is undefined. To check if an error occurred,
1171 use the field_error() function after accessing a field.
1174 return nbt
._bt
_ctf
_get
_variant
(self
._d
)
1176 def _get_struct_field_count(self
):
1178 Return the number of fields contained in the structure.
1179 If the field does not exist or is not of the type requested,
1180 the value returned is undefined.
1183 return nbt
._bt
_ctf
_get
_struct
_field
_count
(self
._d
)
1185 def _get_struct_field_at(self
, i
):
1187 Return the structure's field at position i.
1188 If the field does not exist or is not of the type requested,
1189 the value returned is undefined. To check if an error occurred,
1190 use the field_error() function after accessing a field.
1193 return nbt
._bt
_ctf
_get
_struct
_field
_index
(self
._d
, i
)
1198 Return the value associated with the field according to its type.
1199 Return None on error.
1205 if id == common
.CTFTypeId
.STRING
:
1206 value
= self
._get
_str
()
1207 elif id == common
.CTFTypeId
.ARRAY
:
1208 element_decl
= self
.declaration
.element_declaration
1210 if ((element_decl
.type == common
.CTFTypeId
.INTEGER
1211 and element_decl
.length
== 8)
1212 and (element_decl
.encoding
== common
.CTFStringEncoding
.ASCII
or element_decl
.encoding
== common
.CTFStringEncoding
.UTF8
)):
1213 value
= nbt
._bt
_python
_get
_array
_string
(self
._d
)
1217 for i
in range(self
.declaration
.length
):
1218 element
= self
._get
_array
_element
_at
(i
)
1219 value
.append(element
.value
)
1220 elif id == common
.CTFTypeId
.INTEGER
:
1221 if self
.declaration
.signedness
== 0:
1222 value
= self
._get
_uint
64()
1224 value
= self
._get
_int
64()
1225 elif id == common
.CTFTypeId
.ENUM
:
1226 value
= self
._get
_enum
_str
()
1227 elif id == common
.CTFTypeId
.SEQUENCE
:
1228 element_decl
= self
.declaration
.element_declaration
1230 if ((element_decl
.type == common
.CTFTypeId
.INTEGER
1231 and element_decl
.length
== 8)
1232 and (element_decl
.encoding
== common
.CTFStringEncoding
.ASCII
or element_decl
.encoding
== common
.CTFStringEncoding
.UTF8
)):
1233 value
= nbt
._bt
_python
_get
_sequence
_string
(self
._d
)
1235 seq_len
= self
._get
_sequence
_len
()
1238 for i
in range(seq_len
):
1239 evDef
= self
._get
_sequence
_element
_at
(i
)
1240 value
.append(evDef
.value
)
1241 elif id == common
.CTFTypeId
.FLOAT
:
1242 value
= self
._get
_float
()
1243 elif id == common
.CTFTypeId
.VARIANT
:
1244 variant
= _Definition
.__new
__(_Definition
)
1245 variant
._d
= self
._get
_variant
()
1246 value
= variant
.value
1247 elif id == common
.CTFTypeId
.STRUCT
:
1250 for i
in range(self
._get
_struct
_field
_count
()):
1251 member
= _Definition(self
._get
_struct
_field
_at
(i
), self
.scope
)
1252 value
[member
.name
] = member
.value
1256 "Error occurred while accessing field {} of type {}".format(
1258 common
.CTFTypeId
.type_name(id)))
1264 """Return the scope of a field or None on error."""