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.
50 Creates an empty trace collection.
53 self
._tc
= nbt
._bt
_context
_create
()
56 nbt
._bt
_context
_put
(self
._tc
)
58 def add_trace(self
, path
, format_str
):
60 Adds a trace to the trace collection.
62 *path* is the exact path of the trace on the filesystem.
64 *format_str* is a string indicating the type of trace to
65 add. ``ctf`` is currently the only supported trace format.
67 Returns the corresponding :class:`TraceHandle` instance for
68 this opened trace on success, or ``None`` on error.
70 This function **does not** recurse directories to find a
71 trace. See :meth:`add_traces_recursive` for a recursive
72 version of this function.
75 ret
= nbt
._bt
_context
_add
_trace
(self
._tc
, path
, format_str
,
81 th
= TraceHandle
.__new
__(TraceHandle
)
83 th
._trace
_collection
= self
87 def add_traces_recursive(self
, path
, format_str
):
89 Adds traces to this trace collection by recursively searching
90 in the *path* directory.
92 *format_str* is a string indicating the type of trace to add.
93 ``ctf`` is currently the only supported trace format.
95 Returns a :class:`dict` object mapping full paths to trace
96 handles for each trace found, or ``None`` on error.
98 See also :meth:`add_trace`.
105 for fullpath
, dirs
, files
in os
.walk(path
):
106 if "metadata" in files
:
107 trace_handle
= self
.add_trace(fullpath
, format_str
)
109 if trace_handle
is None:
113 trace_handles
[fullpath
] = trace_handle
116 if noTrace
and error
:
121 def remove_trace(self
, trace_handle
):
123 Removes a trace from the trace collection using its trace
124 handle *trace_handle*.
126 :class:`TraceHandle` objects are returned by :meth:`add_trace`
127 and :meth:`add_traces_recursive`.
131 nbt
._bt
_context
_remove
_trace
(self
._tc
, trace_handle
._id
)
132 except AttributeError:
133 raise TypeError("in remove_trace, argument 2 must be a TraceHandle instance")
138 Generates the ordered :class:`Event` objects of all the opened
139 traces contained in this trace collection.
141 Due to limitations of the native Babeltrace API, only one event
142 may be "alive" at a given time, i.e. a user **should never**
143 store a copy of the events returned by this function for
144 ulterior use. Users shall make sure to copy the information
145 they need *from* an event before accessing the next one.
148 begin_pos_ptr
= nbt
._bt
_python
_create
_iter
_pos
()
149 end_pos_ptr
= nbt
._bt
_python
_create
_iter
_pos
()
150 begin_pos_ptr
.type = nbt
.SEEK_BEGIN
151 end_pos_ptr
.type = nbt
.SEEK_LAST
153 for event
in self
._events
(begin_pos_ptr
, end_pos_ptr
):
156 nbt
._bt
_iter
_free
_pos
(begin_pos_ptr
)
157 nbt
._bt
_iter
_free
_pos
(end_pos_ptr
)
159 def events_timestamps(self
, timestamp_begin
, timestamp_end
):
161 Generates the ordered :class:`Event` objects of all the opened
162 traces contained in this trace collection from *timestamp_begin*
165 *timestamp_begin* and *timestamp_end* are given in nanoseconds
168 See :attr:`events` for notes and limitations.
171 begin_pos_ptr
= nbt
._bt
_python
_create
_iter
_pos
()
172 end_pos_ptr
= nbt
._bt
_python
_create
_iter
_pos
()
173 begin_pos_ptr
.type = end_pos_ptr
.type = nbt
.SEEK_TIME
174 begin_pos_ptr
.u
.seek_time
= timestamp_begin
175 end_pos_ptr
.u
.seek_time
= timestamp_end
177 for event
in self
._events
(begin_pos_ptr
, end_pos_ptr
):
180 nbt
._bt
_iter
_free
_pos
(begin_pos_ptr
)
181 nbt
._bt
_iter
_free
_pos
(end_pos_ptr
)
184 def timestamp_begin(self
):
186 Begin timestamp of this trace collection (nanoseconds since
190 pos_ptr
= nbt
._bt
_iter
_pos
()
191 pos_ptr
.type = nbt
.SEEK_BEGIN
193 return self
._timestamp
_at
_pos
(pos_ptr
)
196 def timestamp_end(self
):
198 End timestamp of this trace collection (nanoseconds since
202 pos_ptr
= nbt
._bt
_iter
_pos
()
203 pos_ptr
.type = nbt
.SEEK_LAST
205 return self
._timestamp
_at
_pos
(pos_ptr
)
207 def _timestamp_at_pos(self
, pos_ptr
):
208 ctf_it_ptr
= nbt
._bt
_ctf
_iter
_create
(self
._tc
, pos_ptr
, pos_ptr
)
210 if ctf_it_ptr
is None:
211 raise NotImplementedError("Creation of multiple iterators is unsupported.")
213 ev_ptr
= nbt
._bt
_ctf
_iter
_read
_event
(ctf_it_ptr
)
214 nbt
._bt
_ctf
_iter
_destroy
(ctf_it_ptr
)
216 ev
= Event
.__new
__(Event
)
221 def _events(self
, begin_pos_ptr
, end_pos_ptr
):
222 ctf_it_ptr
= nbt
._bt
_ctf
_iter
_create
(self
._tc
, begin_pos_ptr
, end_pos_ptr
)
224 if ctf_it_ptr
is None:
225 raise NotImplementedError("Creation of multiple iterators is unsupported.")
228 ev_ptr
= nbt
._bt
_ctf
_iter
_read
_event
(ctf_it_ptr
)
233 ev
= Event
.__new
__(Event
)
238 except GeneratorExit
:
241 ret
= nbt
._bt
_iter
_next
(nbt
._bt
_ctf
_get
_iter
(ctf_it_ptr
))
246 nbt
._bt
_ctf
_iter
_destroy
(ctf_it_ptr
)
249 # Based on enum bt_clock_type in clock-type.h
257 A :class:`TraceHandle` is a handle allowing the user to manipulate
258 a specific trace directly. It is a unique identifier representing a
259 trace, and is not meant to be instantiated by the user.
263 raise NotImplementedError("TraceHandle cannot be instantiated")
266 return "Babeltrace TraceHandle: trace_id('{0}')".format(self
._id
)
271 Numeric ID of this trace handle.
279 Path of the underlying trace.
282 return nbt
._bt
_trace
_handle
_get
_path
(self
._trace
_collection
._tc
,
286 def timestamp_begin(self
):
288 Buffers creation timestamp (nanoseconds since Epoch) of the
292 ret
, value
= nbt
._bt
_trace
_handle
_get
_timestamp
_begin
(
293 self
._trace
_collection
._tc
, self
._id
, _ClockType
.CLOCK_REAL
)
295 raise ValueError("Invalid TraceHandle")
299 def timestamp_end(self
):
301 Buffers destruction timestamp (nanoseconds since Epoch) of the
305 ret
, value
= nbt
._bt
_trace
_handle
_get
_timestamp
_end
(
306 self
._trace
_collection
._tc
, self
._id
, _ClockType
.CLOCK_REAL
)
308 raise ValueError("Invalid TraceHandle")
314 Generates all the :class:`EventDeclaration` objects of the
318 ret
= nbt
._bt
_python
_event
_decl
_listcaller
(self
.id,
319 self
._trace
_collection
._tc
)
321 if not isinstance(ret
, list):
324 ptr_list
, count
= ret
326 for i
in range(count
):
327 tmp
= EventDeclaration
.__new
__(EventDeclaration
)
328 tmp
._ed
= nbt
._bt
_python
_decl
_one
_from
_list
(ptr_list
, i
)
334 # Priority of the scopes when searching for event fields
336 common
.CTFScope
.EVENT_FIELDS
,
337 common
.CTFScope
.EVENT_CONTEXT
,
338 common
.CTFScope
.STREAM_EVENT_CONTEXT
,
339 common
.CTFScope
.STREAM_EVENT_HEADER
,
340 common
.CTFScope
.STREAM_PACKET_CONTEXT
,
341 common
.CTFScope
.TRACE_PACKET_HEADER
345 class Event(collections
.Mapping
):
347 An :class:`Event` object represents a trace event. :class:`Event`
348 objects are returned by :attr:`TraceCollection.events` and are
349 not meant to be instantiated by the user.
351 :class:`Event` has a :class:`dict`-like interface for accessing
352 an event's field value by field name:
354 .. code-block:: python
358 If a field name exists in multiple scopes, the value of the first
359 field found is returned. The scopes are searched in the following
362 1. Event fields (:attr:`babeltrace.common.CTFScope.EVENT_FIELDS`)
363 2. Event context (:attr:`babeltrace.common.CTFScope.EVENT_CONTEXT`)
364 3. Stream event context (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_CONTEXT`)
365 4. Event header (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_HEADER`)
366 5. Packet context (:attr:`babeltrace.common.CTFScope.STREAM_PACKET_CONTEXT`)
367 6. Packet header (:attr:`babeltrace.common.CTFScope.TRACE_PACKET_HEADER`)
369 It is still possible to obtain a field's value from a specific
370 scope using :meth:`field_with_scope`.
372 Field values are returned as native Python types, that is:
374 +-----------------------+----------------------------------+
375 | Field type | Python type |
376 +=======================+==================================+
377 | Integer | :class:`int` |
378 +-----------------------+----------------------------------+
379 | Floating point number | :class:`float` |
380 +-----------------------+----------------------------------+
381 | Enumeration | :class:`str` (enumeration label) |
382 +-----------------------+----------------------------------+
383 | String | :class:`str` |
384 +-----------------------+----------------------------------+
385 | Array | :class:`list` of native Python |
387 +-----------------------+----------------------------------+
388 | Sequence | :class:`list` of native Python |
390 +-----------------------+----------------------------------+
391 | Structure | :class:`dict` mapping field |
392 | | names to native Python objects |
393 +-----------------------+----------------------------------+
395 For example, printing the third element of a sequence named ``seq``
396 in a structure named ``my_struct`` of the ``event``'s field named
397 ``my_field`` is done this way:
399 .. code-block:: python
401 print(event['my_field']['my_struct']['seq'][2])
405 raise NotImplementedError("Event cannot be instantiated")
410 Event name or ``None`` on error.
413 return nbt
._bt
_ctf
_event
_name
(self
._e
)
418 Event timestamp in cycles or -1 on error.
421 return nbt
._bt
_ctf
_get
_cycles
(self
._e
)
426 Event timestamp (nanoseconds since Epoch).
429 ret
, value
= nbt
._bt
_ctf
_get
_timestamp
(self
._e
)
431 raise RuntimeError("Failed to get event timestamp")
437 Event timestamp as a standard :class:`datetime.datetime`
440 Note that the :class:`datetime.datetime` class' precision
441 is limited to microseconds, whereas :attr:`timestamp` provides
442 the event's timestamp with a nanosecond resolution.
445 return datetime
.fromtimestamp(self
.timestamp
/ 1E9
)
447 def field_with_scope(self
, field_name
, scope
):
449 Returns the value of a field named *field_name* within the
450 scope *scope*, or ``None`` if the field cannot be found.
452 *scope* must be one of :class:`babeltrace.common.CTFScope`
456 if scope
not in _scopes
:
457 raise ValueError("Invalid scope provided")
459 field
= self
._field
_with
_scope
(field_name
, scope
)
461 if field
is not None:
464 def field_list_with_scope(self
, scope
):
466 Returns a list of field names in the scope *scope*.
469 if scope
not in _scopes
:
470 raise ValueError("Invalid scope provided")
474 for field
in self
._field
_list
_with
_scope
(scope
):
475 field_names
.append(field
.name
)
482 :class:`TraceHandle` object containing this event, or ``None``
486 ret
= nbt
._bt
_ctf
_event
_get
_handle
_id
(self
._e
)
491 th
= TraceHandle
.__new
__(TraceHandle
)
493 th
._trace
_collection
= self
.get_trace_collection()
498 def trace_collection(self
):
500 :class:`TraceCollection` object containing this event, or
504 trace_collection
= TraceCollection()
505 trace_collection
._tc
= nbt
._bt
_ctf
_event
_get
_context
(self
._e
)
507 if trace_collection
._tc
is not None:
508 return trace_collection
510 def __getitem__(self
, field_name
):
511 field
= self
._field
(field_name
)
513 if field
is not None:
516 raise KeyError(field_name
)
519 for key
in self
.keys():
525 for scope
in _scopes
:
526 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
527 ret
= nbt
._bt
_python
_field
_listcaller
(self
._e
, scope_ptr
)
529 if isinstance(ret
, list):
534 def __contains__(self
, field_name
):
535 return self
._field
(field_name
) is not None
539 Returns the list of field names.
541 Note: field names are unique within the returned list, although
542 a field name could exist in multiple scopes. Use
543 :meth:`field_list_with_scope` to obtain the list of field names
549 for scope
in _scopes
:
550 for name
in self
.field_list_with_scope(scope
):
551 field_names
.add(name
)
553 return list(field_names
)
555 def get(self
, field_name
, default
=None):
557 Returns the value of the field named *field_name*, or *default*
560 See :class:`Event` note about how fields are retrieved by
561 name when multiple fields share the same name in different
565 field
= self
._field
(field_name
)
574 Generates pairs of (field name, field value).
576 This method iterates :meth:`keys` to find field names, which
577 means some fields could be unavailable if other fields share
578 their names in scopes with higher priorities.
581 for field
in self
.keys():
582 yield (field
, self
[field
])
584 def _field_with_scope(self
, field_name
, scope
):
585 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
587 if scope_ptr
is None:
590 definition_ptr
= nbt
._bt
_ctf
_get
_field
(self
._e
, scope_ptr
, field_name
)
592 if definition_ptr
is None:
595 field
= _Definition(definition_ptr
, scope
)
599 def _field(self
, field_name
):
602 for scope
in _scopes
:
603 field
= self
._field
_with
_scope
(field_name
, scope
)
605 if field
is not None:
610 def _field_list_with_scope(self
, scope
):
612 scope_ptr
= nbt
._bt
_ctf
_get
_top
_level
_scope
(self
._e
, scope
)
614 # Returns a list [list_ptr, count]. If list_ptr is NULL, SWIG will only
615 # provide the "count" return value
618 ret
= nbt
._bt
_python
_field
_listcaller
(self
._e
, scope_ptr
)
620 if isinstance(ret
, list):
621 list_ptr
, count
= ret
623 for i
in range(count
):
624 definition_ptr
= nbt
._bt
_python
_field
_one
_from
_list
(list_ptr
, i
)
626 if definition_ptr
is not None:
627 definition
= _Definition(definition_ptr
, scope
)
628 fields
.append(definition
)
633 class FieldError(Exception):
635 Field error, raised when the value of a field cannot be accessed.
638 def __init__(self
, value
):
642 return repr(self
.value
)
645 class EventDeclaration
:
647 An event declaration contains the properties of a class of events,
648 that is, the common properties and fields layout of all the actual
649 recorded events associated with this declaration.
651 This class is not meant to be instantiated by the user. It is
652 returned by :attr:`TraceHandle.events`.
655 MAX_UINT64
= 0xFFFFFFFFFFFFFFFF
658 raise NotImplementedError("EventDeclaration cannot be instantiated")
663 Event name, or ``None`` on error.
666 return nbt
._bt
_ctf
_get
_decl
_event
_name
(self
._ed
)
671 Event numeric ID, or -1 on error.
674 id = nbt
._bt
_ctf
_get
_decl
_event
_id
(self
._ed
)
676 if id == self
.MAX_UINT64
:
684 Generates all the field declarations of this event, going
685 through each scope in the following order:
687 1. Event fields (:attr:`babeltrace.common.CTFScope.EVENT_FIELDS`)
688 2. Event context (:attr:`babeltrace.common.CTFScope.EVENT_CONTEXT`)
689 3. Stream event context (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_CONTEXT`)
690 4. Event header (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_HEADER`)
691 5. Packet context (:attr:`babeltrace.common.CTFScope.STREAM_PACKET_CONTEXT`)
692 6. Packet header (:attr:`babeltrace.common.CTFScope.TRACE_PACKET_HEADER`)
694 All the generated field declarations inherit
695 :class:`FieldDeclaration`, and are among:
697 * :class:`IntegerFieldDeclaration`
698 * :class:`FloatFieldDeclaration`
699 * :class:`EnumerationFieldDeclaration`
700 * :class:`StringFieldDeclaration`
701 * :class:`ArrayFieldDeclaration`
702 * :class:`SequenceFieldDeclaration`
703 * :class:`StructureFieldDeclaration`
704 * :class:`VariantFieldDeclaration`
707 for scope
in _scopes
:
708 for declaration
in self
.fields_scope(scope
):
711 def fields_scope(self
, scope
):
713 Generates all the field declarations of the event's scope
716 *scope* must be one of :class:`babeltrace.common.CTFScope` constants.
718 All the generated field declarations inherit
719 :class:`FieldDeclaration`, and are among:
721 * :class:`IntegerFieldDeclaration`
722 * :class:`FloatFieldDeclaration`
723 * :class:`EnumerationFieldDeclaration`
724 * :class:`StringFieldDeclaration`
725 * :class:`ArrayFieldDeclaration`
726 * :class:`SequenceFieldDeclaration`
727 * :class:`StructureFieldDeclaration`
728 * :class:`VariantFieldDeclaration`
730 ret
= nbt
._by
_python
_field
_decl
_listcaller
(self
._ed
, scope
)
732 if not isinstance(ret
, list):
735 list_ptr
, count
= ret
737 for i
in range(count
):
738 field_decl_ptr
= nbt
._bt
_python
_field
_decl
_one
_from
_list
(list_ptr
, i
)
740 if field_decl_ptr
is not None:
741 decl_ptr
= nbt
._bt
_ctf
_get
_decl
_from
_field
_decl
(field_decl_ptr
)
742 name
= nbt
._bt
_ctf
_get
_decl
_field
_name
(field_decl_ptr
)
743 field_declaration
= _create_field_declaration(decl_ptr
, name
,
745 yield field_declaration
748 class FieldDeclaration
:
750 Base class for concrete field declarations.
752 This class is not meant to be instantiated by the user.
756 raise NotImplementedError("FieldDeclaration cannot be instantiated")
759 return "({0}) {1} {2}".format(common
.CTFScope
.scope_name(self
.scope
),
760 common
.CTFTypeId
.type_name(self
.type),
766 Field name, or ``None`` on error.
774 Field type (one of :class:`babeltrace.common.CTFTypeId`
778 return nbt
._bt
_ctf
_field
_type
(self
._fd
)
783 Field scope (one of:class:`babeltrace.common.CTFScope`
790 class IntegerFieldDeclaration(FieldDeclaration
):
792 Integer field declaration.
796 raise NotImplementedError("IntegerFieldDeclaration cannot be instantiated")
799 def signedness(self
):
801 0 if this integer is unsigned, 1 if signed, or -1 on error.
804 return nbt
._bt
_ctf
_get
_int
_signedness
(self
._fd
)
809 Integer base (:class:`int`), or a negative value on error.
812 return nbt
._bt
_ctf
_get
_int
_base
(self
._fd
)
815 def byte_order(self
):
817 Integer byte order (one of
818 :class:`babeltrace.common.ByteOrder` constants).
821 ret
= nbt
._bt
_ctf
_get
_int
_byte
_order
(self
._fd
)
824 return common
.ByteOrder
.BYTE_ORDER_LITTLE_ENDIAN
826 return common
.ByteOrder
.BYTE_ORDER_BIG_ENDIAN
828 return common
.ByteOrder
.BYTE_ORDER_UNKNOWN
833 Integer size in bits, or a negative value on error.
835 return nbt
._bt
_ctf
_get
_int
_len
(self
._fd
)
844 Integer encoding (one of
845 :class:`babeltrace.common.CTFStringEncoding` constants).
848 return nbt
._bt
_ctf
_get
_encoding
(self
._fd
)
851 class EnumerationFieldDeclaration(FieldDeclaration
):
853 Enumeration field declaration.
857 As of this version, this class is missing some properties.
861 raise NotImplementedError("EnumerationFieldDeclaration cannot be instantiated")
864 class ArrayFieldDeclaration(FieldDeclaration
):
866 Static array field declaration.
870 raise NotImplementedError("ArrayFieldDeclaration cannot be instantiated")
875 Fixed length of this static array (number of contained
876 elements), or a negative value on error.
879 return nbt
._bt
_ctf
_get
_array
_len
(self
._fd
)
882 def element_declaration(self
):
884 Field declaration of the underlying element.
887 field_decl_ptr
= nbt
._bt
_python
_get
_array
_element
_declaration
(self
._fd
)
889 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
892 class SequenceFieldDeclaration(FieldDeclaration
):
894 Sequence (dynamic array) field declaration.
898 As of this version, this class is missing some properties.
902 raise NotImplementedError("SequenceFieldDeclaration cannot be instantiated")
905 def element_declaration(self
):
907 Field declaration of the underlying element.
910 field_decl_ptr
= nbt
._bt
_python
_get
_sequence
_element
_declaration
(self
._fd
)
912 return _create_field_declaration(field_decl_ptr
, "", self
.scope
)
915 class FloatFieldDeclaration(FieldDeclaration
):
917 Floating point number field declaration.
921 As of this version, this class is missing some properties.
925 raise NotImplementedError("FloatFieldDeclaration cannot be instantiated")
928 class StructureFieldDeclaration(FieldDeclaration
):
930 Structure (ordered map of field names to field declarations) field
935 As of this version, this class is missing some properties.
939 raise NotImplementedError("StructureFieldDeclaration cannot be instantiated")
942 class StringFieldDeclaration(FieldDeclaration
):
944 String (NULL-terminated array of bytes) field declaration.
948 As of this version, this class is missing some properties.
952 raise NotImplementedError("StringFieldDeclaration cannot be instantiated")
955 class VariantFieldDeclaration(FieldDeclaration
):
957 Variant (dynamic selection between different types) field declaration.
961 As of this version, this class is missing some properties.
965 raise NotImplementedError("VariantFieldDeclaration cannot be instantiated")
970 Return the last error code encountered while
971 accessing a field and reset the error flag.
972 Return 0 if no error, a negative value otherwise.
975 return nbt
._bt
_ctf
_field
_get
_error
()
978 def _create_field_declaration(declaration_ptr
, name
, scope
):
980 Private field declaration factory.
983 if declaration_ptr
is None:
984 raise ValueError("declaration_ptr must be valid")
985 if scope
not in _scopes
:
986 raise ValueError("Invalid scope provided")
988 type = nbt
._bt
_ctf
_field
_type
(declaration_ptr
)
991 if type == common
.CTFTypeId
.INTEGER
:
992 declaration
= IntegerFieldDeclaration
.__new
__(IntegerFieldDeclaration
)
993 elif type == common
.CTFTypeId
.ENUM
:
994 declaration
= EnumerationFieldDeclaration
.__new
__(EnumerationFieldDeclaration
)
995 elif type == common
.CTFTypeId
.ARRAY
:
996 declaration
= ArrayFieldDeclaration
.__new
__(ArrayFieldDeclaration
)
997 elif type == common
.CTFTypeId
.SEQUENCE
:
998 declaration
= SequenceFieldDeclaration
.__new
__(SequenceFieldDeclaration
)
999 elif type == common
.CTFTypeId
.FLOAT
:
1000 declaration
= FloatFieldDeclaration
.__new
__(FloatFieldDeclaration
)
1001 elif type == common
.CTFTypeId
.STRUCT
:
1002 declaration
= StructureFieldDeclaration
.__new
__(StructureFieldDeclaration
)
1003 elif type == common
.CTFTypeId
.STRING
:
1004 declaration
= StringFieldDeclaration
.__new
__(StringFieldDeclaration
)
1005 elif type == common
.CTFTypeId
.VARIANT
:
1006 declaration
= VariantFieldDeclaration
.__new
__(VariantFieldDeclaration
)
1010 declaration
._fd
= declaration_ptr
1011 declaration
._s
= scope
1012 declaration
._name
= name
1018 def __init__(self
, definition_ptr
, scope
):
1019 self
._d
= definition_ptr
1022 if scope
not in _scopes
:
1023 ValueError("Invalid scope provided")
1027 """Return the name of a field or None on error."""
1029 return nbt
._bt
_ctf
_field
_name
(self
._d
)
1033 """Return the type of a field or -1 if unknown."""
1035 return nbt
._bt
_ctf
_field
_type
(nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
))
1038 def declaration(self
):
1039 """Return the associated Definition object."""
1041 return _create_field_declaration(
1042 nbt
._bt
_ctf
_get
_decl
_from
_def
(self
._d
), self
.name
, self
.scope
)
1044 def _get_enum_str(self
):
1046 Return the string matching the current enumeration.
1047 Return None on error.
1050 return nbt
._bt
_ctf
_get
_enum
_str
(self
._d
)
1052 def _get_array_element_at(self
, index
):
1054 Return the array's element at position index.
1055 Return None on error
1058 array_ptr
= nbt
._bt
_python
_get
_array
_from
_def
(self
._d
)
1060 if array_ptr
is None:
1063 definition_ptr
= nbt
._bt
_array
_index
(array_ptr
, index
)
1065 if definition_ptr
is None:
1068 return _Definition(definition_ptr
, self
.scope
)
1070 def _get_sequence_len(self
):
1072 Return the len of a sequence or a negative
1076 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
1078 return nbt
._bt
_sequence
_len
(seq
)
1080 def _get_sequence_element_at(self
, index
):
1082 Return the sequence's element at position index,
1083 otherwise return None
1086 seq
= nbt
._bt
_python
_get
_sequence
_from
_def
(self
._d
)
1089 definition_ptr
= nbt
._bt
_sequence
_index
(seq
, index
)
1091 if definition_ptr
is not None:
1092 return _Definition(definition_ptr
, self
.scope
)
1094 def _get_uint64(self
):
1096 Return the value associated with the field.
1097 If the field does not exist or is not of the type requested,
1098 the value returned is undefined. To check if an error occured,
1099 use the field_error() function after accessing a field.
1102 return nbt
._bt
_ctf
_get
_uint
64(self
._d
)
1104 def _get_int64(self
):
1106 Return the value associated with the field.
1107 If the field does not exist or is not of the type requested,
1108 the value returned is undefined. To check if an error occured,
1109 use the field_error() function after accessing a field.
1112 return nbt
._bt
_ctf
_get
_int
64(self
._d
)
1114 def _get_char_array(self
):
1116 Return the value associated with the field.
1117 If the field does not exist or is not of the type requested,
1118 the value returned is undefined. To check if an error occurred,
1119 use the field_error() function after accessing a field.
1122 return nbt
._bt
_ctf
_get
_char
_array
(self
._d
)
1126 Return the value associated with the field.
1127 If the field does not exist or is not of the type requested,
1128 the value returned is undefined. To check if an error occurred,
1129 use the field_error() function after accessing a field.
1132 return nbt
._bt
_ctf
_get
_string
(self
._d
)
1134 def _get_float(self
):
1136 Return the value associated with the field.
1137 If the field does not exist or is not of the type requested,
1138 the value returned is undefined. To check if an error occurred,
1139 use the field_error() function after accessing a field.
1142 return nbt
._bt
_ctf
_get
_float
(self
._d
)
1144 def _get_variant(self
):
1146 Return the variant's selected field.
1147 If the field does not exist or is not of the type requested,
1148 the value returned is undefined. To check if an error occurred,
1149 use the field_error() function after accessing a field.
1152 return nbt
._bt
_ctf
_get
_variant
(self
._d
)
1154 def _get_struct_field_count(self
):
1156 Return the number of fields contained in the structure.
1157 If the field does not exist or is not of the type requested,
1158 the value returned is undefined.
1161 return nbt
._bt
_ctf
_get
_struct
_field
_count
(self
._d
)
1163 def _get_struct_field_at(self
, i
):
1165 Return the structure's field at position i.
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
_struct
_field
_index
(self
._d
, i
)
1176 Return the value associated with the field according to its type.
1177 Return None on error.
1183 if id == common
.CTFTypeId
.STRING
:
1184 value
= self
._get
_str
()
1185 elif id == common
.CTFTypeId
.ARRAY
:
1186 element_decl
= self
.declaration
.element_declaration
1188 if ((element_decl
.type == common
.CTFTypeId
.INTEGER
1189 and element_decl
.length
== 8)
1190 and (element_decl
.encoding
== common
.CTFStringEncoding
.ASCII
or element_decl
.encoding
== common
.CTFStringEncoding
.UTF8
)):
1191 value
= nbt
._bt
_python
_get
_array
_string
(self
._d
)
1195 for i
in range(self
.declaration
.length
):
1196 element
= self
._get
_array
_element
_at
(i
)
1197 value
.append(element
.value
)
1198 elif id == common
.CTFTypeId
.INTEGER
:
1199 if self
.declaration
.signedness
== 0:
1200 value
= self
._get
_uint
64()
1202 value
= self
._get
_int
64()
1203 elif id == common
.CTFTypeId
.ENUM
:
1204 value
= self
._get
_enum
_str
()
1205 elif id == common
.CTFTypeId
.SEQUENCE
:
1206 element_decl
= self
.declaration
.element_declaration
1208 if ((element_decl
.type == common
.CTFTypeId
.INTEGER
1209 and element_decl
.length
== 8)
1210 and (element_decl
.encoding
== common
.CTFStringEncoding
.ASCII
or element_decl
.encoding
== common
.CTFStringEncoding
.UTF8
)):
1211 value
= nbt
._bt
_python
_get
_sequence
_string
(self
._d
)
1213 seq_len
= self
._get
_sequence
_len
()
1216 for i
in range(seq_len
):
1217 evDef
= self
._get
_sequence
_element
_at
(i
)
1218 value
.append(evDef
.value
)
1219 elif id == common
.CTFTypeId
.FLOAT
:
1220 value
= self
._get
_float
()
1221 elif id == common
.CTFTypeId
.VARIANT
:
1222 variant
= _Definition
.__new
__(_Definition
)
1223 variant
._d
= self
._get
_variant
()
1224 value
= variant
.value
1225 elif id == common
.CTFTypeId
.STRUCT
:
1228 for i
in range(self
._get
_struct
_field
_count
()):
1229 member
= _Definition(self
._get
_struct
_field
_at
(i
), self
.scope
)
1230 value
[member
.name
] = member
.value
1234 "Error occurred while accessing field {} of type {}".format(
1236 common
.CTFTypeId
.type_name(id)))
1242 """Return the scope of a field or None on error."""