# The MIT License (MIT)
#
-# Copyright (c) 2015 Philippe Proulx <pproulx@efficios.com>
+# Copyright (c) 2015-2016 Philippe Proulx <pproulx@efficios.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
raise ConfigError('barectf metadata error', e)
def _augment_metadata_env(self, meta):
- env = meta.env
-
- env['domain'] = 'bare'
- env['tracer_name'] = 'barectf'
version_tuple = barectf.get_version_tuple()
- env['tracer_major'] = version_tuple[0]
- env['tracer_minor'] = version_tuple[1]
- env['tracer_patch'] = version_tuple[2]
- env['barectf_gen_date'] = str(datetime.datetime.now().isoformat())
+ base_env = {
+ 'domain': 'bare',
+ 'tracer_name': 'barectf' ,
+ 'tracer_major': version_tuple[0],
+ 'tracer_minor': version_tuple[1],
+ 'tracer_patch': version_tuple[2],
+ 'barectf_gen_date': str(datetime.datetime.now().isoformat()),
+ }
+
+ base_env.update(meta.env)
+ meta.env = base_env
@property
def version(self):
@prefix.setter
def prefix(self, value):
- if not is_valid_identifier(value):
+ if not _is_valid_identifier(value):
raise ConfigError('prefix must be a valid C identifier')
self._prefix = value
])
-def is_valid_identifier(iden):
+def _is_valid_identifier(iden):
if not _re_iden.match(iden):
return False
raise ConfigError('invalid trace packet header type', e)
for stream_name, stream in meta.streams.items():
- if not is_valid_identifier(stream_name):
+ if not _is_valid_identifier(stream_name):
raise ConfigError('stream name "{}" is not a valid C identifier'.format(stream_name))
self._cur_entity = _Entity.STREAM_PACKET_CONTEXT
try:
for ev_name, ev in stream.events.items():
- if not is_valid_identifier(ev_name):
+ if not _is_valid_identifier(ev_name):
raise ConfigError('event name "{}" is not a valid C identifier'.format(ev_name))
self._cur_entity = _Entity.EVENT_CONTEXT
self._cur_entity = _Entity.EVENT_PAYLOAD
- if ev.payload_type is None:
- raise ConfigError('missing payload type in event "{}"'.format(ev_name), e)
-
try:
self._validate_entity(ev.payload_type)
except Exception as e:
raise ConfigError('invalid payload type in event "{}"'.format(ev_name), e)
- if not ev.payload_type.fields:
- raise ConfigError('empty payload type in event "{}"'.format(ev_name), e)
+ if stream.is_event_empty(ev):
+ raise ConfigError('event "{}" is empty'.format(ev_name))
except Exception as e:
raise ConfigError('invalid stream "{}"'.format(stream_name), e)
if len(self._meta.streams) > 1:
# yes
if t is None:
- raise ConfigError('need "stream_id" field in trace packet header type, but trace packet header type is missing')
+ raise ConfigError('need "stream_id" field in trace packet header type (more than one stream), but trace packet header type is missing')
if type(t) is not metadata.Struct:
- raise ConfigError('need "stream_id" field in trace packet header type, but trace packet header type is not a structure type')
+ raise ConfigError('need "stream_id" field in trace packet header type (more than one stream), but trace packet header type is not a structure type')
if 'stream_id' not in t.fields:
- raise ConfigError('need "stream_id" field in trace packet header type')
+ raise ConfigError('need "stream_id" field in trace packet header type (more than one stream)')
# validate "magic" and "stream_id" types
if type(t) is not metadata.Struct:
if field_type.signed:
raise ConfigError('"stream_id" field in trace packet header type must be an unsigned integer type')
+
+ # "id" size can fit all event IDs
+ if len(self._meta.streams) > (1 << field_type.size):
+ raise ConfigError('"stream_id" field\' size in trace packet header type is too small for the number of trace streams')
elif field_name == 'uuid':
if self._meta.trace.uuid is None:
raise ConfigError('"uuid" field in trace packet header type specified, but no trace UUID provided')
t = stream.packet_context_type
if type(t) is None:
- return
+ raise ConfigError('missing "packet-context-type" property in stream object')
if type(t) is not metadata.Struct:
- return
+ raise ConfigError('"packet-context-type": expecting a structure type')
# "timestamp_begin", if exists, is an unsigned integer type,
# mapped to a clock
+ ts_begin = None
+
if 'timestamp_begin' in t.fields:
ts_begin = t.fields['timestamp_begin']
# "timestamp_end", if exists, is an unsigned integer type,
# mapped to a clock
+ ts_end = None
+
if 'timestamp_end' in t.fields:
ts_end = t.fields['timestamp_end']
if (('timestamp_begin' in t.fields) ^ ('timestamp_end' in t.fields)):
raise ConfigError('"timestamp_begin" and "timestamp_end" fields must be defined together in stream packet context type')
+ # "timestamp_begin" and "timestamp_end" are mapped to the same clock
+ if ts_begin is not None and ts_end is not None:
+ if ts_begin.property_mappings[0].object.name != ts_end.property_mappings[0].object.name:
+ raise ConfigError('"timestamp_begin" and "timestamp_end" fields must be mapped to the same clock object in stream packet context type')
+
# "events_discarded", if exists, is an unsigned integer type
if 'events_discarded' in t.fields:
events_discarded = t.fields['events_discarded']
if content_size.signed:
raise ConfigError('"content_size" field in stream packet context type must be an unsigned integer type')
+ # "packet_size" size should be greater than or equal to "content_size" size
+ if content_size.size > packet_size.size:
+ raise ConfigError('"content_size" field size must be lesser than or equal to "packet_size" field size')
+
def _validate_stream_event_header(self, stream):
t = stream.event_header_type
if len(stream.events) > 1:
# yes
if t is None:
- raise ConfigError('need "id" field in stream event header type, but stream event header type is missing')
+ raise ConfigError('need "id" field in stream event header type (more than one event), but stream event header type is missing')
if type(t) is not metadata.Struct:
- raise ConfigError('need "id" field in stream event header type, but stream event header type is not a structure type')
+ raise ConfigError('need "id" field in stream event header type (more than one event), but stream event header type is not a structure type')
if 'id' not in t.fields:
- raise ConfigError('need "id" field in stream event header type')
+ raise ConfigError('need "id" field in stream event header type (more than one event)')
# validate "id" and "timestamp" types
if type(t) is not metadata.Struct:
ts = t.fields['timestamp']
if type(ts) is not metadata.Integer:
- raise ConfigError('"ts" field in stream event header type must be an integer type')
+ raise ConfigError('"timestamp" field in stream event header type must be an integer type')
if ts.signed:
- raise ConfigError('"ts" field in stream event header type must be an unsigned integer type')
+ raise ConfigError('"timestamp" field in stream event header type must be an unsigned integer type')
if not ts.property_mappings:
- raise ConfigError('"ts" field in stream event header type must be mapped to a clock')
+ raise ConfigError('"timestamp" field in stream event header type must be mapped to a clock')
- # "id" is an unsigned integer type
if 'id' in t.fields:
eid = t.fields['id']
+ # "id" is an unsigned integer type
if type(eid) is not metadata.Integer:
raise ConfigError('"id" field in stream event header type must be an integer type')
if eid.signed:
raise ConfigError('"id" field in stream event header type must be an unsigned integer type')
+ # "id" size can fit all event IDs
+ if len(stream.events) > (1 << eid.size):
+ raise ConfigError('"id" field\' size in stream event header type is too small for the number of stream events')
+
def _validate_stream(self, stream):
self._validate_stream_packet_context(stream)
self._validate_stream_event_header(stream)
self._stack_pop()
def _visit_array_type(self, t):
- if not t.is_static:
+ if t.is_variable_length:
# find length type
try:
length_type = self._lookup_path(t.length, t)
# Since type inheritance allows types to be only partially defined at
# any place in the configuration, this validator validates that actual
-# trace, stream, and event types are all complete and valid.
+# trace, stream, and event types are all complete and valid. Therefore
+# an invalid, but unusued type alias is accepted.
class _MetadataTypesHistologyValidator:
def __init__(self):
self._type_to_validate_type_histology_func = {
def _validate_enum_histology(self, t):
# integer type is set
if t.value_type is None:
- raise ConfigError('missing enumeration type\'s integer type')
+ raise ConfigError('missing enumeration type\'s value type')
# there's at least one member
if not t.members:
raise ConfigError('enumeration type needs at least one member')
- # no overlapping values
+ # no overlapping values and all values are valid considering
+ # the value type
ranges = []
+ if t.value_type.signed:
+ value_min = -(1 << t.value_type.size - 1)
+ value_max = (1 << (t.value_type.size - 1)) - 1
+ else:
+ value_min = 0
+ value_max = (1 << t.value_type.size) - 1
+
for label, value in t.members.items():
for rg in ranges:
if value[0] <= rg[1] and rg[0] <= value[1]:
raise ConfigError('enumeration type\'s member "{}" overlaps another member'.format(label))
+ fmt = 'enumeration type\'s member "{}": value {} is outside the value type range [{}, {}]'
+
+ if value[0] < value_min or value[0] > value_max:
+ raise ConfigError(fmt.format(label, value[0], value_min, value_max))
+
+ if value[1] < value_min or value[1] > value_max:
+ raise ConfigError(fmt.format(label, value[1], value_min, value_max))
+
ranges.append(value)
def _validate_string_histology(self, t):
if t is None:
return
- # entity cannot be an array
- if type(t) is metadata.Array:
- raise ConfigError('cannot use an array here')
+ if type(t) is not metadata.Struct:
+ raise ConfigError('expecting a structure type')
self._validate_type_histology(t)
raise ConfigError('invalid event context type for event "{}"'.format(ev_name), e)
# validate event payload type
- if ev.payload_type is None:
- raise ConfigError('event payload type must exist in event "{}"'.format(ev_name))
-
- # TODO: also check arrays, sequences, and variants
- if type(ev.payload_type) is metadata.Struct:
- if not ev.payload_type.fields:
- raise ConfigError('event payload type must have at least one field for event "{}"'.format(ev_name))
-
try:
self._validate_entity_type_histology(ev.payload_type)
except Exception as e:
metadata.Variant: self._create_variant,
}
self._include_dirs = include_dirs
- self._include_dirs.append(os.getcwd())
self._ignore_include_not_found = ignore_include_not_found
self._dump_config = dump_config
if 'align' in node:
align = node['align']
- if not _is_int_prop(align):
- raise ConfigError('"align" property of integer type object must be an integer')
+ if align is None:
+ obj.set_default_align()
+ else:
+ if not _is_int_prop(align):
+ raise ConfigError('"align" property of integer type object must be an integer')
- if not _is_valid_alignment(align):
- raise ConfigError('invalid alignment: {}'.format(align))
+ if not _is_valid_alignment(align):
+ raise ConfigError('invalid alignment: {}'.format(align))
- obj.align = align
+ obj.align = align
# signed
if 'signed' in node:
signed = node['signed']
- if not _is_bool_prop(signed):
- raise ConfigError('"signed" property of integer type object must be a boolean')
+ if signed is None:
+ obj.set_default_signed()
+ else:
+ if not _is_bool_prop(signed):
+ raise ConfigError('"signed" property of integer type object must be a boolean')
- obj.signed = signed
+ obj.signed = signed
# byte order
if 'byte-order' in node:
byte_order = node['byte-order']
- if not _is_str_prop(byte_order):
- raise ConfigError('"byte-order" property of integer type object must be a string ("le" or "be")')
+ if byte_order is None:
+ obj.byte_order = self._bo
+ else:
+ if not _is_str_prop(byte_order):
+ raise ConfigError('"byte-order" property of integer type object must be a string ("le" or "be")')
+
+ byte_order = _byte_order_str_to_bo(byte_order)
- byte_order = _byte_order_str_to_bo(byte_order)
+ if byte_order is None:
+ raise ConfigError('invalid "byte-order" property in integer type object')
- if byte_order is None:
- raise ConfigError('invalid "byte-order" property in integer type object')
+ obj.byte_order = byte_order
else:
- byte_order = self._bo
-
- obj.byte_order = byte_order
+ obj.byte_order = self._bo
# base
if 'base' in node:
base = node['base']
- if not _is_str_prop(base):
- raise ConfigError('"base" property of integer type object must be a string ("bin", "oct", "dec", or "hex")')
-
- if base == 'bin':
- base = 2
- elif base == 'oct':
- base = 8
- elif base == 'dec':
- base = 10
- elif base == 'hex':
- base = 16
+ if base is None:
+ obj.set_default_base()
else:
- raise ConfigError('unknown "base" property value: "{}" ("bin", "oct", "dec", and "hex" are accepted)'.format(base))
+ if not _is_str_prop(base):
+ raise ConfigError('"base" property of integer type object must be a string ("bin", "oct", "dec", or "hex")')
+
+ if base == 'bin':
+ base = 2
+ elif base == 'oct':
+ base = 8
+ elif base == 'dec':
+ base = 10
+ elif base == 'hex':
+ base = 16
+ else:
+ raise ConfigError('unknown "base" property value: "{}" ("bin", "oct", "dec", and "hex" are accepted)'.format(base))
- obj.base = base
+ obj.base = base
# encoding
if 'encoding' in node:
encoding = node['encoding']
- if not _is_str_prop(encoding):
- raise ConfigError('"encoding" property of integer type object must be a string ("none", "ascii", or "utf-8")')
+ if encoding is None:
+ obj.set_default_encoding()
+ else:
+ if not _is_str_prop(encoding):
+ raise ConfigError('"encoding" property of integer type object must be a string ("none", "ascii", or "utf-8")')
- encoding = _encoding_str_to_encoding(encoding)
+ encoding = _encoding_str_to_encoding(encoding)
- if encoding is None:
- raise ConfigError('invalid "encoding" property in integer type object')
+ if encoding is None:
+ raise ConfigError('invalid "encoding" property in integer type object')
- obj.encoding = encoding
+ obj.encoding = encoding
# property mappings
if 'property-mappings' in node:
prop_mappings = node['property-mappings']
- if not _is_array_prop(prop_mappings):
- raise ConfigError('"property-mappings" property of integer type object must be an array')
-
- if len(prop_mappings) > 1:
- raise ConfigError('length of "property-mappings" array in integer type object must be 1')
+ if prop_mappings is None:
+ obj.set_default_property_mappings()
+ else:
+ if not _is_array_prop(prop_mappings):
+ raise ConfigError('"property-mappings" property of integer type object must be an array')
- del obj.property_mappings[:]
+ if len(prop_mappings) > 1:
+ raise ConfigError('length of "property-mappings" array in integer type object must be 1')
- for index, prop_mapping in enumerate(prop_mappings):
- if not _is_assoc_array_prop(prop_mapping):
- raise ConfigError('elements of "property-mappings" property of integer type object must be associative arrays')
+ for index, prop_mapping in enumerate(prop_mappings):
+ if not _is_assoc_array_prop(prop_mapping):
+ raise ConfigError('elements of "property-mappings" property of integer type object must be associative arrays')
- if 'type' not in prop_mapping:
- raise ConfigError('missing "type" property in integer type object\'s "property-mappings" array\'s element #{}'.format(index))
+ if 'type' not in prop_mapping:
+ raise ConfigError('missing "type" property in integer type object\'s "property-mappings" array\'s element #{}'.format(index))
- prop_type = prop_mapping['type']
+ prop_type = prop_mapping['type']
- if not _is_str_prop(prop_type):
- raise ConfigError('"type" property of integer type object\'s "property-mappings" array\'s element #{} must be a string'.format(index))
+ if not _is_str_prop(prop_type):
+ raise ConfigError('"type" property of integer type object\'s "property-mappings" array\'s element #{} must be a string'.format(index))
- if prop_type == 'clock':
- self._set_int_clock_prop_mapping(obj, prop_mapping)
- else:
- raise ConfigError('unknown property mapping type "{}" in integer type object\'s "property-mappings" array\'s element #{}'.format(prop_type, index))
+ if prop_type == 'clock':
+ self._set_int_clock_prop_mapping(obj, prop_mapping)
+ else:
+ raise ConfigError('unknown property mapping type "{}" in integer type object\'s "property-mappings" array\'s element #{}'.format(prop_type, index))
return obj
if 'align' in node:
align = node['align']
- if not _is_int_prop(align):
- raise ConfigError('"align" property of floating point number type object must be an integer')
+ if align is None:
+ obj.set_default_align()
+ else:
+ if not _is_int_prop(align):
+ raise ConfigError('"align" property of floating point number type object must be an integer')
- if not _is_valid_alignment(align):
- raise ConfigError('invalid alignment: {}'.format(align))
+ if not _is_valid_alignment(align):
+ raise ConfigError('invalid alignment: {}'.format(align))
- obj.align = align
+ obj.align = align
# byte order
if 'byte-order' in node:
byte_order = node['byte-order']
- if not _is_str_prop(byte_order):
- raise ConfigError('"byte-order" property of floating point number type object must be a string ("le" or "be")')
+ if byte_order is None:
+ obj.byte_order = self._bo
+ else:
+ if not _is_str_prop(byte_order):
+ raise ConfigError('"byte-order" property of floating point number type object must be a string ("le" or "be")')
- byte_order = _byte_order_str_to_bo(byte_order)
+ byte_order = _byte_order_str_to_bo(byte_order)
- if byte_order is None:
- raise ConfigError('invalid "byte-order" property in floating point number type object')
+ if byte_order is None:
+ raise ConfigError('invalid "byte-order" property in floating point number type object')
else:
- byte_order = self._bo
-
- obj.byte_order = byte_order
+ obj.byte_order = self._bo
return obj
# value type
if 'value-type' in node:
+ value_type_node = node['value-type']
+
try:
- obj.value_type = self._create_type(node['value-type'])
+ obj.value_type = self._create_type(value_type_node)
except Exception as e:
raise ConfigError('cannot create enumeration type\'s integer type', e)
raise ConfigError('"members" property of enumeration type object must be an array')
cur = 0
+ last_value = obj.last_value
+
+ if last_value is None:
+ cur = 0
+ else:
+ cur = last_value + 1
for index, m_node in enumerate(members_node):
if not _is_str_prop(m_node) and not _is_assoc_array_prop(m_node):
value = (cur, cur)
cur += 1
else:
+ unk_prop = _get_first_unknown_prop(m_node, [
+ 'label',
+ 'value',
+ ])
+
+ if unk_prop:
+ raise ConfigError('unknown enumeration type member object property: "{}"'.format(unk_prop))
+
if 'label' not in m_node:
raise ConfigError('missing "label" property in enumeration member #{}'.format(index))
if 'encoding' in node:
encoding = node['encoding']
- if not _is_str_prop(encoding):
- raise ConfigError('"encoding" property of string type object must be a string ("none", "ascii", or "utf-8")')
+ if encoding is None:
+ obj.set_default_encoding()
+ else:
+ if not _is_str_prop(encoding):
+ raise ConfigError('"encoding" property of string type object must be a string ("none", "ascii", or "utf-8")')
- encoding = _encoding_str_to_encoding(encoding)
+ encoding = _encoding_str_to_encoding(encoding)
- if encoding is None:
- raise ConfigError('invalid "encoding" property in string type object')
+ if encoding is None:
+ raise ConfigError('invalid "encoding" property in string type object')
- obj.encoding = encoding
+ obj.encoding = encoding
return obj
if 'min-align' in node:
min_align = node['min-align']
- if not _is_int_prop(min_align):
- raise ConfigError('"min-align" property of structure type object must be an integer')
+ if min_align is None:
+ obj.set_default_min_align()
+ else:
+ if not _is_int_prop(min_align):
+ raise ConfigError('"min-align" property of structure type object must be an integer')
- if not _is_valid_alignment(min_align):
- raise ConfigError('invalid minimum alignment: {}'.format(min_align))
+ if not _is_valid_alignment(min_align):
+ raise ConfigError('invalid minimum alignment: {}'.format(min_align))
- obj.min_align = min_align
+ obj.min_align = min_align
# fields
if 'fields' in node:
fields = node['fields']
- if not _is_assoc_array_prop(fields):
- raise ConfigError('"fields" property of structure type object must be an associative array')
+ if fields is None:
+ obj.set_default_fields()
+ else:
+ if not _is_assoc_array_prop(fields):
+ raise ConfigError('"fields" property of structure type object must be an associative array')
- for field_name, field_node in fields.items():
- if not is_valid_identifier(field_name):
- raise ConfigError('"{}" is not a valid field name for structure type'.format(field_name))
+ for field_name, field_node in fields.items():
+ if not _is_valid_identifier(field_name):
+ raise ConfigError('"{}" is not a valid field name for structure type'.format(field_name))
- try:
- obj.fields[field_name] = self._create_type(field_node)
- except Exception as e:
- raise ConfigError('cannot create structure type\'s field "{}"'.format(field_name), e)
+ try:
+ obj.fields[field_name] = self._create_type(field_node)
+ except Exception as e:
+ raise ConfigError('cannot create structure type\'s field "{}"'.format(field_name), e)
return obj
# element type
if 'element-type' in node:
+ element_type_node = node['element-type']
+
try:
obj.element_type = self._create_type(node['element-type'])
except Exception as e:
# do not validate type names for the moment; will be done in a
# second phase
for type_name, type_node in types.items():
- if not is_valid_identifier(type_name):
+ if not _is_valid_identifier(type_name):
raise ConfigError('"{}" is not a valid type name for variant type'.format(type_name))
try:
return t
if not _is_assoc_array_prop(type_node):
- raise ConfigError('type objects must be associative arrays')
+ raise ConfigError('type objects must be associative arrays or strings (type alias name)')
# inherit:
# v2.0: "inherit"
ta_node = metadata_node['type-aliases']
+ if ta_node is None:
+ return
+
if not _is_assoc_array_prop(ta_node):
raise ConfigError('"type-aliases" property (metadata) must be an associative array')
if 'uuid' in node:
uuidp = node['uuid']
- if not _is_str_prop(uuidp):
- raise ConfigError('"uuid" property of clock object must be a string')
+ if uuidp is None:
+ clock.set_default_uuid()
+ else:
+ if not _is_str_prop(uuidp):
+ raise ConfigError('"uuid" property of clock object must be a string')
- try:
- uuidp = uuid.UUID(uuidp)
- except:
- raise ConfigError('malformed UUID (clock object): "{}"'.format(uuidp))
+ try:
+ uuidp = uuid.UUID(uuidp)
+ except:
+ raise ConfigError('malformed UUID (clock object): "{}"'.format(uuidp))
- clock.uuid = uuidp
+ clock.uuid = uuidp
# description
if 'description' in node:
desc = node['description']
- if not _is_str_prop(desc):
- raise ConfigError('"description" property of clock object must be a string')
+ if desc is None:
+ clock.set_default_description()
+ else:
+ if not _is_str_prop(desc):
+ raise ConfigError('"description" property of clock object must be a string')
- clock.description = desc
+ clock.description = desc
# frequency
if 'freq' in node:
freq = node['freq']
- if not _is_int_prop(freq):
- raise ConfigError('"freq" property of clock object must be an integer')
+ if freq is None:
+ clock.set_default_freq()
+ else:
+ if not _is_int_prop(freq):
+ raise ConfigError('"freq" property of clock object must be an integer')
- if freq < 1:
- raise ConfigError('invalid clock frequency: {}'.format(freq))
+ if freq < 1:
+ raise ConfigError('invalid clock frequency: {}'.format(freq))
- clock.freq = freq
+ clock.freq = freq
# error cycles
if 'error-cycles' in node:
error_cycles = node['error-cycles']
- if not _is_int_prop(error_cycles):
- raise ConfigError('"error-cycles" property of clock object must be an integer')
+ if error_cycles is None:
+ clock.set_default_error_cycles()
+ else:
+ if not _is_int_prop(error_cycles):
+ raise ConfigError('"error-cycles" property of clock object must be an integer')
- if error_cycles < 0:
- raise ConfigError('invalid clock error cycles: {}'.format(error_cycles))
+ if error_cycles < 0:
+ raise ConfigError('invalid clock error cycles: {}'.format(error_cycles))
- clock.error_cycles = error_cycles
+ clock.error_cycles = error_cycles
# offset
if 'offset' in node:
offset = node['offset']
- if not _is_assoc_array_prop(offset):
- raise ConfigError('"offset" property of clock object must be an associative array')
+ if offset is None:
+ clock.set_default_offset_seconds()
+ clock.set_default_offset_cycles()
+ else:
+ if not _is_assoc_array_prop(offset):
+ raise ConfigError('"offset" property of clock object must be an associative array')
- unk_prop = _get_first_unknown_prop(offset, ['cycles', 'seconds'])
+ unk_prop = _get_first_unknown_prop(offset, ['cycles', 'seconds'])
- if unk_prop:
- raise ConfigError('unknown clock object\'s offset property: "{}"'.format(unk_prop))
+ if unk_prop:
+ raise ConfigError('unknown clock object\'s offset property: "{}"'.format(unk_prop))
- # cycles
- if 'cycles' in offset:
- offset_cycles = offset['cycles']
+ # cycles
+ if 'cycles' in offset:
+ offset_cycles = offset['cycles']
- if not _is_int_prop(offset_cycles):
- raise ConfigError('"cycles" property of clock object\'s offset property must be an integer')
+ if offset_cycles is None:
+ clock.set_default_offset_cycles()
+ else:
+ if not _is_int_prop(offset_cycles):
+ raise ConfigError('"cycles" property of clock object\'s offset property must be an integer')
- if offset_cycles < 0:
- raise ConfigError('invalid clock offset cycles: {}'.format(offset_cycles))
+ if offset_cycles < 0:
+ raise ConfigError('invalid clock offset cycles: {}'.format(offset_cycles))
- clock.offset_cycles = offset_cycles
+ clock.offset_cycles = offset_cycles
- # seconds
- if 'seconds' in offset:
- offset_seconds = offset['seconds']
+ # seconds
+ if 'seconds' in offset:
+ offset_seconds = offset['seconds']
- if not _is_int_prop(offset_seconds):
- raise ConfigError('"seconds" property of clock object\'s offset property must be an integer')
+ if offset_seconds is None:
+ clock.set_default_offset_seconds()
+ else:
+ if not _is_int_prop(offset_seconds):
+ raise ConfigError('"seconds" property of clock object\'s offset property must be an integer')
- if offset_seconds < 0:
- raise ConfigError('invalid clock offset seconds: {}'.format(offset_seconds))
+ if offset_seconds < 0:
+ raise ConfigError('invalid clock offset seconds: {}'.format(offset_seconds))
- clock.offset_seconds = offset_seconds
+ clock.offset_seconds = offset_seconds
# absolute
if 'absolute' in node:
absolute = node['absolute']
- if not _is_bool_prop(absolute):
- raise ConfigError('"absolute" property of clock object must be a boolean')
+ if absolute is None:
+ clock.set_default_absolute()
+ else:
+ if not _is_bool_prop(absolute):
+ raise ConfigError('"absolute" property of clock object must be a boolean')
- clock.absolute = absolute
+ clock.absolute = absolute
# return C type:
# v2.0: "return-ctype"
return_ctype_node = node[return_ctype_prop]
if return_ctype_node is not None:
- if not _is_str_prop(return_ctype_node):
- raise ConfigError('"{}" property of clock object must be a string'.format(return_ctype_prop))
+ if return_ctype_node is None:
+ clock.set_default_return_ctype()
+ else:
+ if not _is_str_prop(return_ctype_node):
+ raise ConfigError('"{}" property of clock object must be a string'.format(return_ctype_prop))
- clock.return_ctype = return_ctype_node
+ clock.return_ctype = return_ctype_node
return clock
clocks_node = metadata_node['clocks']
+ if clocks_node is None:
+ return
+
if not _is_assoc_array_prop(clocks_node):
raise ConfigError('"clocks" property (metadata) must be an associative array')
for clock_name, clock_node in clocks_node.items():
- if not is_valid_identifier(clock_name):
+ if not _is_valid_identifier(clock_name):
raise ConfigError('invalid clock name: "{}"'.format(clock_name))
if clock_name in self._clocks:
env_node = metadata_node['env']
+ if env_node is None:
+ return env
+
if not _is_assoc_array_prop(env_node):
raise ConfigError('"env" property (metadata) must be an associative array')
if env_name in env:
raise ConfigError('duplicate environment variable "{}"'.format(env_name))
- if not is_valid_identifier(env_name):
+ if not _is_valid_identifier(env_name):
raise ConfigError('invalid environment variable name: "{}"'.format(env_name))
if not _is_int_prop(env_value) and not _is_str_prop(env_value):
trace.byte_order = self._bo
# UUID
- if 'uuid' in trace_node:
+ if 'uuid' in trace_node and trace_node['uuid'] is not None:
uuidp = trace_node['uuid']
if not _is_str_prop(uuidp):
trace.uuid = uuidp
# packet header type
- if 'packet-header-type' in trace_node:
+ if 'packet-header-type' in trace_node and trace_node['packet-header-type'] is not None:
try:
ph_type = self._create_type(trace_node['packet-header-type'])
except Exception as e:
if unk_prop:
raise ConfigError('unknown event object property: "{}"'.format(unk_prop))
- if 'log-level' in event_node:
+ if 'log-level' in event_node and event_node['log-level'] is not None:
ll_node = event_node['log-level']
if _is_str_prop(ll_node):
- ll = self._lookup_log_level(event_node['log-level'])
+ ll_value = self._lookup_log_level(event_node['log-level'])
- if ll is None:
+ if ll_value is None:
raise ConfigError('cannot find log level "{}"'.format(ll_node))
+
+ ll = metadata.LogLevel(event_node['log-level'], ll_value)
elif _is_int_prop(ll_node):
if ll_node < 0:
raise ConfigError('invalid log level value {}: value must be positive'.format(ll_node))
- ll = ll_node
+ ll = metadata.LogLevel(None, ll_node)
else:
raise ConfigError('"log-level" property must be either a string or an integer')
event.log_level = ll
- if 'context-type' in event_node:
+ if 'context-type' in event_node and event_node['context-type'] is not None:
+ ctx_type_node = event_node['context-type']
+
try:
t = self._create_type(event_node['context-type'])
except Exception as e:
event.context_type = t
- if 'payload-type' not in event_node:
- raise ConfigError('missing "payload-type" property in event object')
-
- try:
- t = self._create_type(event_node['payload-type'])
- except Exception as e:
- raise ConfigError('cannot create event\'s payload type object', e)
+ if 'payload-type' in event_node and event_node['payload-type'] is not None:
+ try:
+ t = self._create_type(event_node['payload-type'])
+ except Exception as e:
+ raise ConfigError('cannot create event\'s payload type object', e)
- event.payload_type = t
+ event.payload_type = t
return event
if unk_prop:
raise ConfigError('unknown stream object property: "{}"'.format(unk_prop))
- if 'packet-context-type' in stream_node:
+ if 'packet-context-type' in stream_node and stream_node['packet-context-type'] is not None:
try:
t = self._create_type(stream_node['packet-context-type'])
except Exception as e:
stream.packet_context_type = t
- if 'event-header-type' in stream_node:
+ if 'event-header-type' in stream_node and stream_node['event-header-type'] is not None:
try:
t = self._create_type(stream_node['event-header-type'])
except Exception as e:
stream.event_header_type = t
- if 'event-context-type' in stream_node:
+ if 'event-context-type' in stream_node and stream_node['event-context-type'] is not None:
try:
t = self._create_type(stream_node['event-context-type'])
except Exception as e:
events = stream_node['events']
- if not _is_assoc_array_prop(events):
- raise ConfigError('"events" property of stream object must be an associative array')
+ if events is not None:
+ if not _is_assoc_array_prop(events):
+ raise ConfigError('"events" property of stream object must be an associative array')
- if not events:
- raise ConfigError('at least one event is needed within a stream object')
+ if not events:
+ raise ConfigError('at least one event is needed within a stream object')
- cur_id = 0
+ cur_id = 0
- for ev_name, ev_node in events.items():
- try:
- ev = self._create_event(ev_node)
- except Exception as e:
- raise ConfigError('cannot create event "{}"'.format(ev_name), e)
+ for ev_name, ev_node in events.items():
+ try:
+ ev = self._create_event(ev_node)
+ except Exception as e:
+ raise ConfigError('cannot create event "{}"'.format(ev_name), e)
- ev.id = cur_id
- ev.name = ev_name
- stream.events[ev_name] = ev
- cur_id += 1
+ ev.id = cur_id
+ ev.name = ev_name
+ stream.events[ev_name] = ev
+ cur_id += 1
return stream
return version
def _get_prefix(self, root):
+ def_prefix = 'barectf_'
+
if 'prefix' not in root:
- return 'barectf_'
+ return def_prefix
prefix_node = root['prefix']
+ if prefix_node is None:
+ return def_prefix
+
if not _is_str_prop(prefix_node):
raise ConfigError('"prefix" property (configuration) must be a string')
- if not is_valid_identifier(prefix_node):
+ if not _is_valid_identifier(prefix_node):
raise ConfigError('"prefix" property (configuration) must be a valid C identifier')
return prefix_node
return None
def _get_include_paths(self, include_node):
+ if include_node is None:
+ return []
+
if _is_str_prop(include_node):
return [include_node]
- elif _is_array_prop(include_node):
+
+ if _is_array_prop(include_node):
for include_path in include_node:
if not _is_str_prop(include_path):
raise ConfigError('invalid include property: expecting array of strings')