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")
139 Generates the ordered :class:`Event` objects of all the opened
140 traces contained in this trace collection.
142 Due to limitations of the native Babeltrace API, only one event
143 may be "alive" at a given time, i.e. a user **should never**
144 store a copy of the events returned by this function for
145 ulterior use. Users shall make sure to copy the information
146 they need *from* an event before accessing the next one.
149 begin_pos_ptr
= nbt
._bt
_python
_create
_iter
_pos
()
150 end_pos_ptr
= nbt
._bt
_python
_create
_iter
_pos
()
152 if not self
.intersect_mode
:
153 begin_pos_ptr
.type = nbt
.SEEK_BEGIN
154 end_pos_ptr
.type = nbt
.SEEK_LAST
156 for event
in self
._events
(begin_pos_ptr
, end_pos_ptr
):
159 nbt
._bt
_iter
_free
_pos
(begin_pos_ptr
)
160 nbt
._bt
_iter
_free
_pos
(end_pos_ptr
)
162 def events_timestamps(self
, timestamp_begin
, timestamp_end
):
164 Generates the ordered :class:`Event` objects of all the opened
165 traces contained in this trace collection from *timestamp_begin*
168 *timestamp_begin* and *timestamp_end* are given in nanoseconds
171 See :attr:`events` for notes and limitations.
174 begin_pos_ptr
= nbt
._bt
_python
_create
_iter
_pos
()
175 end_pos_ptr
= nbt
._bt
_python
_create
_iter
_pos
()
176 begin_pos_ptr
.type = end_pos_ptr
.type = nbt
.SEEK_TIME
177 begin_pos_ptr
.u
.seek_time
= timestamp_begin
178 end_pos_ptr
.u
.seek_time
= timestamp_end
180 for event
in self
._events
(begin_pos_ptr
, end_pos_ptr
):
183 nbt
._bt
_iter
_free
_pos
(begin_pos_ptr
)
184 nbt
._bt
_iter
_free
_pos
(end_pos_ptr
)
187 def timestamp_begin(self
):
189 Begin timestamp of this trace collection (nanoseconds since
193 pos_ptr
= nbt
._bt
_iter
_pos
()
194 pos_ptr
.type = nbt
.SEEK_BEGIN
196 return self
._timestamp
_at
_pos
(pos_ptr
)
199 def timestamp_end(self
):
201 End timestamp of this trace collection (nanoseconds since
205 pos_ptr
= nbt
._bt
_iter
_pos
()
206 pos_ptr
.type = nbt
.SEEK_LAST
208 return self
._timestamp
_at
_pos
(pos_ptr
)
210 def _timestamp_at_pos(self
, pos_ptr
):
211 ctf_it_ptr
= nbt
._bt
_ctf
_iter
_create
(self
._tc
, pos_ptr
, pos_ptr
)
213 if ctf_it_ptr
is None:
214 raise NotImplementedError("Creation of multiple iterators is unsupported.")
216 ev_ptr
= nbt
._bt
_ctf
_iter
_read
_event
(ctf_it_ptr
)
217 nbt
._bt
_ctf
_iter
_destroy
(ctf_it_ptr
)
219 ev
= Event
.__new
__(Event
)
224 def _events(self
, begin_pos_ptr
, end_pos_ptr
):
225 if self
.intersect_mode
:
226 has_intersection
= nbt
._bt
_python
_has
_intersection
(self
._tc
)
227 if not has_intersection
:
228 # There are no events to provide.
231 ctf_it_ptr
= nbt
._bt
_python
_ctf
_iter
_create
_intersect
(
232 self
._tc
, begin_pos_ptr
, end_pos_ptr
235 ctf_it_ptr
= nbt
._bt
_ctf
_iter
_create
(
236 self
._tc
, begin_pos_ptr
, end_pos_ptr
239 if ctf_it_ptr
is None:
240 raise NotImplementedError("Creation of multiple iterators is unsupported.")
243 ev_ptr
= nbt
._bt
_ctf
_iter
_read
_event
(ctf_it_ptr
)
248 ev
= Event
.__new
__(Event
)
253 except GeneratorExit
:
256 ret
= nbt
._bt
_iter
_next
(nbt
._bt
_ctf
_get
_iter
(ctf_it_ptr
))
261 nbt
._bt
_ctf
_iter
_destroy
(ctf_it_ptr
)
264 # Based on enum bt_clock_type in clock-type.h
272 A :class:`TraceHandle` is a handle allowing the user to manipulate
273 a specific trace directly. It is a unique identifier representing a
274 trace, and is not meant to be instantiated by the user.
278 raise NotImplementedError("TraceHandle cannot be instantiated")
281 return "Babeltrace TraceHandle: trace_id('{0}')".format(self
._id
)
286 Numeric ID of this trace handle.
294 Path of the underlying trace.
297 return nbt
._bt
_trace
_handle
_get
_path
(self
._trace
_collection
._tc
,
301 def timestamp_begin(self
):
303 Buffers creation timestamp (nanoseconds since Epoch) of the
307 ret
, value
= nbt
._bt
_trace
_handle
_get
_timestamp
_begin
(
308 self
._trace
_collection
._tc
, self
._id
, _ClockType
.CLOCK_REAL
)
310 raise ValueError("Invalid TraceHandle")
314 def timestamp_end(self
):
316 Buffers destruction timestamp (nanoseconds since Epoch) of the
320 ret
, value
= nbt
._bt
_trace
_handle
_get
_timestamp
_end
(
321 self
._trace
_collection
._tc
, self
._id
, _ClockType
.CLOCK_REAL
)
323 raise ValueError("Invalid TraceHandle")
329 Generates all the :class:`EventDeclaration` objects of the
333 ret
= nbt
._bt
_python
_event
_decl
_listcaller
(self
.id,
334 self
._trace
_collection
._tc
)
336 if not isinstance(ret
, list):
339 ptr_list
, count
= ret
341 for i
in range(count
):
342 tmp
= EventDeclaration
.__new
__(EventDeclaration
)
343 tmp
._ed
= nbt
._bt
_python
_decl
_one
_from
_list
(ptr_list
, i
)
349 # Priority of the scopes when searching for event fields
351 common
.CTFScope
.EVENT_FIELDS
,
352 common
.CTFScope
.EVENT_CONTEXT
,
353 common
.CTFScope
.STREAM_EVENT_CONTEXT
,
354 common
.CTFScope
.STREAM_EVENT_HEADER
,
355 common
.CTFScope
.STREAM_PACKET_CONTEXT
,
356 common
.CTFScope
.TRACE_PACKET_HEADER
360 class Event(collections
.Mapping
):
362 An :class:`Event` object represents a trace event. :class:`Event`
363 objects are returned by :attr:`TraceCollection.events` and are
364 not meant to be instantiated by the user.
366 :class:`Event` has a :class:`dict`-like interface for accessing
367 an event's field value by field name:
369 .. code-block:: python
373 If a field name exists in multiple scopes, the value of the first
374 field found is returned. The scopes are searched in the following
377 1. Event fields (:attr:`babeltrace.common.CTFScope.EVENT_FIELDS`)
378 2. Event context (:attr:`babeltrace.common.CTFScope.EVENT_CONTEXT`)
379 3. Stream event context (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_CONTEXT`)
380 4. Event header (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_HEADER`)
381 5. Packet context (:attr:`babeltrace.common.CTFScope.STREAM_PACKET_CONTEXT`)
382 6. Packet header (:attr:`babeltrace.common.CTFScope.TRACE_PACKET_HEADER`)
384 It is still possible to obtain a field's value from a specific
385 scope using :meth:`field_with_scope`.
387 Field values are returned as native Python types, that is:
389 +-----------------------+----------------------------------+
390 | Field type | Python type |
391 +=======================+==================================+
392 | Integer | :class:`int` |
393 +-----------------------+----------------------------------+
394 | Floating point number | :class:`float` |
395 +-----------------------+----------------------------------+
396 | Enumeration | :class:`str` (enumeration label) |
397 +-----------------------+----------------------------------+
398 | String | :class:`str` |
399 +-----------------------+----------------------------------+
400 | Array | :class:`list` of native Python |
402 +-----------------------+----------------------------------+
403 | Sequence | :class:`list` of native Python |
405 +-----------------------+----------------------------------+
406 | Structure | :class:`dict` mapping field |
407 | | names to native Python objects |
408 +-----------------------+----------------------------------+
410 For example, printing the third element of a sequence named ``seq``
411 in a structure named ``my_struct`` of the ``event``'s field named
412 ``my_field`` is done this way:
414 .. code-block:: python
416 print(event['my_field']['my_struct']['seq'][2])
420 raise NotImplementedError("Event cannot be instantiated")
425 Event name or ``None`` on error.
428 return nbt
._bt
_ctf
_event
_name
(self
._e
)
433 Event timestamp in cycles or -1 on error.
436 return nbt
._bt
_ctf
_get
_cycles
(self
._e
)
441 Event timestamp (nanoseconds since Epoch).
444 ret
, value
= nbt
._bt
_ctf
_get
_timestamp
(self
._e
)
446 raise RuntimeError("Failed to get event timestamp")
452 Event timestamp as a standard :class:`datetime.datetime`
455 Note that the :class:`datetime.datetime` class' precision
456 is limited to microseconds, whereas :attr:`timestamp` provides
457 the event's timestamp with a nanosecond resolution.
460 return datetime
.fromtimestamp(self
.timestamp
/ 1E9
)
462 def field_with_scope(self
, field_name
, scope
):
464 Returns the value of a field named *field_name* within the
465 scope *scope*, or ``None`` if the field cannot be found.
467 *scope* must be one of :class:`babeltrace.common.CTFScope`
471 if scope
not in _scopes
:
472 raise ValueError("Invalid scope provided")
474 field
= self
._field
_with
_scope
(field_name
, scope
)
476 if field
is not None:
479 def field_list_with_scope(self
, scope
):
481 Returns a list of field names in the scope *scope*.
484 if scope
not in _scopes
:
485 raise ValueError("Invalid scope provided")
489 for field
in self
._field
_list
_with
_scope
(scope
):
490 field_names
.append(field
.name
)
497 :class:`TraceHandle` object containing this event, or ``None``
501 ret
= nbt
._bt
_ctf
_event
_get
_handle
_id
(self
._e
)
506 th
= TraceHandle
.__new
__(TraceHandle
)
508 th
._trace
_collection
= self
.get_trace_collection()
513 def trace_collection(self
):
515 :class:`TraceCollection` object containing this event, or
519 trace_collection
= TraceCollection()
520 trace_collection
._tc
= nbt
._bt
_ctf
_event
_get
_context
(self
._e
)
522 if trace_collection
._tc
is not None:
523 return trace_collection
525 def __getitem__(self
, field_name
):
526 field
= self
._field
(field_name
)
528 if field
is not None:
531 raise KeyError(field_name
)
534 for key
in self
.keys():
540 for scope
in _scopes
:
541 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
542 ret
= nbt
._bt
_python
_field
_listcaller
(self
._e
, scope_ptr
)
544 if isinstance(ret
, list):
549 def __contains__(self
, field_name
):
550 return self
._field
(field_name
) is not None
554 Returns the list of field names.
556 Note: field names are unique within the returned list, although
557 a field name could exist in multiple scopes. Use
558 :meth:`field_list_with_scope` to obtain the list of field names
564 for scope
in _scopes
:
565 for name
in self
.field_list_with_scope(scope
):
566 field_names
.add(name
)
568 return list(field_names
)
570 def get(self
, field_name
, default
=None):
572 Returns the value of the field named *field_name*, or *default*
575 See :class:`Event` note about how fields are retrieved by
576 name when multiple fields share the same name in different
580 field
= self
._field
(field_name
)
589 Generates pairs of (field name, field value).
591 This method iterates :meth:`keys` to find field names, which
592 means some fields could be unavailable if other fields share
593 their names in scopes with higher priorities.
596 for field
in self
.keys():
597 yield (field
, self
[field
])
599 def _field_with_scope(self
, field_name
, scope
):
600 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
602 if scope_ptr
is None:
605 definition_ptr
= nbt
._bt
_ctf
_get
_field
(self
._e
, scope_ptr
, field_name
)
607 if definition_ptr
is None:
610 field
= _Definition(definition_ptr
, scope
)
614 def _field(self
, field_name
):
617 for scope
in _scopes
:
618 field
= self
._field
_with
_scope
(field_name
, scope
)
620 if field
is not None:
625 def _field_list_with_scope(self
, scope
):
627 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
629 # Returns a list [list_ptr, count]. If list_ptr is NULL, SWIG will only
630 # provide the "count" return value
633 ret
= nbt
._bt
_python
_field
_listcaller
(self
._e
, scope_ptr
)
635 if isinstance(ret
, list):
636 list_ptr
, count
= ret
638 for i
in range(count
):
639 definition_ptr
= nbt
._bt
_python
_field
_one
_from
_list
(list_ptr
, i
)
641 if definition_ptr
is not None:
642 definition
= _Definition(definition_ptr
, scope
)
643 fields
.append(definition
)
648 class FieldError(Exception):
650 Field error, raised when the value of a field cannot be accessed.
653 def __init__(self
, value
):
657 return repr(self
.value
)
660 class EventDeclaration
:
662 An event declaration contains the properties of a class of events,
663 that is, the common properties and fields layout of all the actual
664 recorded events associated with this declaration.
666 This class is not meant to be instantiated by the user. It is
667 returned by :attr:`TraceHandle.events`.
670 MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
673 raise NotImplementedError("EventDeclaration cannot be instantiated")
678 Event name, or ``None`` on error.
681 return nbt
._bt
_ctf
_get
_decl
_event
_name
(self
._ed
)
686 Event numeric ID, or -1 on error.
689 id = nbt
._bt
_ctf
_get
_decl
_event
_id
(self
._ed
)
691 if id == self
.MAX_UINT64
:
699 Generates all the field declarations of this event, going
700 through each scope in the following order:
702 1. Event fields (:attr:`babeltrace.common.CTFScope.EVENT_FIELDS`)
703 2. Event context (:attr:`babeltrace.common.CTFScope.EVENT_CONTEXT`)
704 3. Stream event context (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_CONTEXT`)
705 4. Event header (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_HEADER`)
706 5. Packet context (:attr:`babeltrace.common.CTFScope.STREAM_PACKET_CONTEXT`)
707 6. Packet header (:attr:`babeltrace.common.CTFScope.TRACE_PACKET_HEADER`)
709 All the generated field declarations inherit
710 :class:`FieldDeclaration`, and are among:
712 * :class:`IntegerFieldDeclaration`
713 * :class:`FloatFieldDeclaration`
714 * :class:`EnumerationFieldDeclaration`
715 * :class:`StringFieldDeclaration`
716 * :class:`ArrayFieldDeclaration`
717 * :class:`SequenceFieldDeclaration`
718 * :class:`StructureFieldDeclaration`
719 * :class:`VariantFieldDeclaration`
722 for scope
in _scopes
:
723 for declaration
in self
.fields_scope(scope
):
726 def fields_scope(self
, scope
):
728 Generates all the field declarations of the event's scope
731 *scope* must be one of :class:`babeltrace.common.CTFScope` constants.
733 All the generated field declarations inherit
734 :class:`FieldDeclaration`, and are among:
736 * :class:`IntegerFieldDeclaration`
737 * :class:`FloatFieldDeclaration`
738 * :class:`EnumerationFieldDeclaration`
739 * :class:`StringFieldDeclaration`
740 * :class:`ArrayFieldDeclaration`
741 * :class:`SequenceFieldDeclaration`
742 * :class:`StructureFieldDeclaration`
743 * :class:`VariantFieldDeclaration`
745 ret
= nbt
._by
_python
_field
_decl
_listcaller
(self
._ed
, scope
)
747 if not isinstance(ret
, list):
750 list_ptr
, count
= ret
752 for i
in range(count
):
753 field_decl_ptr
= nbt
._bt
_python
_field
_decl
_one
_from
_list
(list_ptr
, i
)
755 if field_decl_ptr
is not None:
756 decl_ptr
= nbt
._bt
_ctf
_get
_decl
_from
_field
_decl
(field_decl_ptr
)
757 name
= nbt
._bt
_ctf
_get
_decl
_field
_name
(field_decl_ptr
)
758 field_declaration
= _create_field_declaration(decl_ptr
, name
,
760 yield field_declaration
763 class FieldDeclaration
:
765 Base class for concrete field declarations.
767 This class is not meant to be instantiated by the user.
771 raise NotImplementedError("FieldDeclaration cannot be instantiated")
774 return "({0}) {1} {2}".format(common
.CTFScope
.scope_name(self
.scope
),
775 common
.CTFTypeId
.type_name(self
.type),
781 Field name, or ``None`` on error.
789 Field type (one of :class:`babeltrace.common.CTFTypeId`
793 return nbt
._bt
_ctf
_field
_type
(self
._fd
)
798 Field scope (one of:class:`babeltrace.common.CTFScope`
805 class IntegerFieldDeclaration(FieldDeclaration
):
807 Integer field declaration.
811 raise NotImplementedError("IntegerFieldDeclaration cannot be instantiated")
814 def signedness(self
):
816 0 if this integer is unsigned, 1 if signed, or -1 on error.
819 return nbt
._bt
_ctf
_get
_int
_signedness
(self
._fd
)
824 Integer base (:class:`int`), or a negative value on error.
827 return nbt
._bt
_ctf
_get
_int
_base
(self
._fd
)
830 def byte_order(self
):
832 Integer byte order (one of
833 :class:`babeltrace.common.ByteOrder` constants).
836 ret
= nbt
._bt
_ctf
_get
_int
_byte
_order
(self
._fd
)
839 return common
.ByteOrder
.BYTE_ORDER_LITTLE_ENDIAN
841 return common
.ByteOrder
.BYTE_ORDER_BIG_ENDIAN
843 return common
.ByteOrder
.BYTE_ORDER_UNKNOWN
848 Integer size in bits, or a negative value on error.
850 return nbt
._bt
_ctf
_get
_int
_len
(self
._fd
)
859 Integer encoding (one of
860 :class:`babeltrace.common.CTFStringEncoding` constants).
863 return nbt
._bt
_ctf
_get
_encoding
(self
._fd
)
866 class EnumerationFieldDeclaration(FieldDeclaration
):
868 Enumeration field declaration.
872 As of this version, this class is missing some properties.
876 raise NotImplementedError("EnumerationFieldDeclaration cannot be instantiated")
879 class ArrayFieldDeclaration(FieldDeclaration
):
881 Static array field declaration.
885 raise NotImplementedError("ArrayFieldDeclaration cannot be instantiated")
890 Fixed length of this static array (number of contained
891 elements), or a negative value on error.
894 return nbt
._bt
_ctf
_get
_array
_len
(self
._fd
)
897 def element_declaration(self
):
899 Field declaration of the underlying element.
902 field_decl_ptr
= nbt
._bt
_python
_get
_array
_element
_declaration
(self
._fd
)
904 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
907 class SequenceFieldDeclaration(FieldDeclaration
):
909 Sequence (dynamic array) field declaration.
913 As of this version, this class is missing some properties.
917 raise NotImplementedError("SequenceFieldDeclaration cannot be instantiated")
920 def element_declaration(self
):
922 Field declaration of the underlying element.
925 field_decl_ptr
= nbt
._bt
_python
_get
_sequence
_element
_declaration
(self
._fd
)
927 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
930 class FloatFieldDeclaration(FieldDeclaration
):
932 Floating point number field declaration.
936 As of this version, this class is missing some properties.
940 raise NotImplementedError("FloatFieldDeclaration cannot be instantiated")
943 class StructureFieldDeclaration(FieldDeclaration
):
945 Structure (ordered map of field names to field declarations) field
950 As of this version, this class is missing some properties.
954 raise NotImplementedError("StructureFieldDeclaration cannot be instantiated")
957 class StringFieldDeclaration(FieldDeclaration
):
959 String (NULL-terminated array of bytes) field declaration.
963 As of this version, this class is missing some properties.
967 raise NotImplementedError("StringFieldDeclaration cannot be instantiated")
970 class VariantFieldDeclaration(FieldDeclaration
):
972 Variant (dynamic selection between different types) field declaration.
976 As of this version, this class is missing some properties.
980 raise NotImplementedError("VariantFieldDeclaration cannot be instantiated")
985 Return the last error code encountered while
986 accessing a field and reset the error flag.
987 Return 0 if no error, a negative value otherwise.
990 return nbt
._bt
_ctf
_field
_get
_error
()
993 def _create_field_declaration(declaration_ptr
, name
, scope
):
995 Private field declaration factory.
998 if declaration_ptr
is None:
999 raise ValueError("declaration_ptr must be valid")
1000 if scope
not in _scopes
:
1001 raise ValueError("Invalid scope provided")
1003 type = nbt
._bt
_ctf
_field
_type
(declaration_ptr
)
1006 if type == common
.CTFTypeId
.INTEGER
:
1007 declaration
= IntegerFieldDeclaration
.__new
__(IntegerFieldDeclaration
)
1008 elif type == common
.CTFTypeId
.ENUM
:
1009 declaration
= EnumerationFieldDeclaration
.__new
__(EnumerationFieldDeclaration
)
1010 elif type == common
.CTFTypeId
.ARRAY
:
1011 declaration
= ArrayFieldDeclaration
.__new
__(ArrayFieldDeclaration
)
1012 elif type == common
.CTFTypeId
.SEQUENCE
:
1013 declaration
= SequenceFieldDeclaration
.__new
__(SequenceFieldDeclaration
)
1014 elif type == common
.CTFTypeId
.FLOAT
:
1015 declaration
= FloatFieldDeclaration
.__new
__(FloatFieldDeclaration
)
1016 elif type == common
.CTFTypeId
.STRUCT
:
1017 declaration
= StructureFieldDeclaration
.__new
__(StructureFieldDeclaration
)
1018 elif type == common
.CTFTypeId
.STRING
:
1019 declaration
= StringFieldDeclaration
.__new
__(StringFieldDeclaration
)
1020 elif type == common
.CTFTypeId
.VARIANT
:
1021 declaration
= VariantFieldDeclaration
.__new
__(VariantFieldDeclaration
)
1025 declaration
._fd
= declaration_ptr
1026 declaration
._s
= scope
1027 declaration
._name
= name
1033 def __init__(self
, definition_ptr
, scope
):
1034 self
._d
= definition_ptr
1037 if scope
not in _scopes
:
1038 ValueError("Invalid scope provided")
1042 """Return the name of a field or None on error."""
1044 return nbt
._bt
_ctf
_field
_name
(self
._d
)
1048 """Return the type of a field or -1 if unknown."""
1050 return nbt
._bt
_ctf
_field
_type
(nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
))
1053 def declaration(self
):
1054 """Return the associated Definition object."""
1056 return _create_field_declaration(
1057 nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
), self
.name
, self
.scope
)
1059 def _get_enum_str(self
):
1061 Return the string matching the current enumeration.
1062 Return None on error.
1065 return nbt
._bt
_ctf
_get
_enum
_str
(self
._d
)
1067 def _get_array_element_at(self
, index
):
1069 Return the array's element at position index.
1070 Return None on error
1073 array_ptr
= nbt
._bt
_python
_get
_array
_from
_def
(self
._d
)
1075 if array_ptr
is None:
1078 definition_ptr
= nbt
._bt
_array
_index
(array_ptr
, index
)
1080 if definition_ptr
is None:
1083 return _Definition(definition_ptr
, self
.scope
)
1085 def _get_sequence_len(self
):
1087 Return the len of a sequence or a negative
1091 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
1093 return nbt
._bt
_sequence
_len
(seq
)
1095 def _get_sequence_element_at(self
, index
):
1097 Return the sequence's element at position index,
1098 otherwise return None
1101 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
1104 definition_ptr
= nbt
._bt
_sequence
_index
(seq
, index
)
1106 if definition_ptr
is not None:
1107 return _Definition(definition_ptr
, self
.scope
)
1109 def _get_uint64(self
):
1111 Return the value associated with the field.
1112 If the field does not exist or is not of the type requested,
1113 the value returned is undefined. To check if an error occured,
1114 use the field_error() function after accessing a field.
1117 return nbt
._bt
_ctf
_get
_uint
64(self
._d
)
1119 def _get_int64(self
):
1121 Return the value associated with the field.
1122 If the field does not exist or is not of the type requested,
1123 the value returned is undefined. To check if an error occured,
1124 use the field_error() function after accessing a field.
1127 return nbt
._bt
_ctf
_get
_int
64(self
._d
)
1129 def _get_char_array(self
):
1131 Return the value associated with the field.
1132 If the field does not exist or is not of the type requested,
1133 the value returned is undefined. To check if an error occurred,
1134 use the field_error() function after accessing a field.
1137 return nbt
._bt
_ctf
_get
_char
_array
(self
._d
)
1141 Return the value associated with the field.
1142 If the field does not exist or is not of the type requested,
1143 the value returned is undefined. To check if an error occurred,
1144 use the field_error() function after accessing a field.
1147 return nbt
._bt
_ctf
_get
_string
(self
._d
)
1149 def _get_float(self
):
1151 Return the value associated with the field.
1152 If the field does not exist or is not of the type requested,
1153 the value returned is undefined. To check if an error occurred,
1154 use the field_error() function after accessing a field.
1157 return nbt
._bt
_ctf
_get
_float
(self
._d
)
1159 def _get_variant(self
):
1161 Return the variant's selected field.
1162 If the field does not exist or is not of the type requested,
1163 the value returned is undefined. To check if an error occurred,
1164 use the field_error() function after accessing a field.
1167 return nbt
._bt
_ctf
_get
_variant
(self
._d
)
1169 def _get_struct_field_count(self
):
1171 Return the number of fields contained in the structure.
1172 If the field does not exist or is not of the type requested,
1173 the value returned is undefined.
1176 return nbt
._bt
_ctf
_get
_struct
_field
_count
(self
._d
)
1178 def _get_struct_field_at(self
, i
):
1180 Return the structure's field at position i.
1181 If the field does not exist or is not of the type requested,
1182 the value returned is undefined. To check if an error occurred,
1183 use the field_error() function after accessing a field.
1186 return nbt
._bt
_ctf
_get
_struct
_field
_index
(self
._d
, i
)
1191 Return the value associated with the field according to its type.
1192 Return None on error.
1198 if id == common
.CTFTypeId
.STRING
:
1199 value
= self
._get
_str
()
1200 elif id == common
.CTFTypeId
.ARRAY
:
1201 element_decl
= self
.declaration
.element_declaration
1203 if ((element_decl
.type == common
.CTFTypeId
.INTEGER
1204 and element_decl
.length
== 8)
1205 and (element_decl
.encoding
== common
.CTFStringEncoding
.ASCII
or element_decl
.encoding
== common
.CTFStringEncoding
.UTF8
)):
1206 value
= nbt
._bt
_python
_get
_array
_string
(self
._d
)
1210 for i
in range(self
.declaration
.length
):
1211 element
= self
._get
_array
_element
_at
(i
)
1212 value
.append(element
.value
)
1213 elif id == common
.CTFTypeId
.INTEGER
:
1214 if self
.declaration
.signedness
== 0:
1215 value
= self
._get
_uint
64()
1217 value
= self
._get
_int
64()
1218 elif id == common
.CTFTypeId
.ENUM
:
1219 value
= self
._get
_enum
_str
()
1220 elif id == common
.CTFTypeId
.SEQUENCE
:
1221 element_decl
= self
.declaration
.element_declaration
1223 if ((element_decl
.type == common
.CTFTypeId
.INTEGER
1224 and element_decl
.length
== 8)
1225 and (element_decl
.encoding
== common
.CTFStringEncoding
.ASCII
or element_decl
.encoding
== common
.CTFStringEncoding
.UTF8
)):
1226 value
= nbt
._bt
_python
_get
_sequence
_string
(self
._d
)
1228 seq_len
= self
._get
_sequence
_len
()
1231 for i
in range(seq_len
):
1232 evDef
= self
._get
_sequence
_element
_at
(i
)
1233 value
.append(evDef
.value
)
1234 elif id == common
.CTFTypeId
.FLOAT
:
1235 value
= self
._get
_float
()
1236 elif id == common
.CTFTypeId
.VARIANT
:
1237 variant
= _Definition
.__new
__(_Definition
)
1238 variant
._d
= self
._get
_variant
()
1239 value
= variant
.value
1240 elif id == common
.CTFTypeId
.STRUCT
:
1243 for i
in range(self
._get
_struct
_field
_count
()):
1244 member
= _Definition(self
._get
_struct
_field
_at
(i
), self
.scope
)
1245 value
[member
.name
] = member
.value
1249 "Error occurred while accessing field {} of type {}".format(
1251 common
.CTFTypeId
.type_name(id)))
1257 """Return the scope of a field or None on error."""