diff --git a/inc/taitypes.h b/inc/taitypes.h index 05ad0b0..9dc6faa 100644 --- a/inc/taitypes.h +++ b/inc/taitypes.h @@ -196,6 +196,19 @@ typedef struct _tai_object_map_list_t tai_object_map_t *list; } tai_object_map_list_t; +// Forward declaration of tai_attribute_value_t for tai_attr_value_list_t +union _tai_attribute_value_t; +typedef union _tai_attribute_value_t tai_attribute_value_t; + +typedef struct _tai_attr_value_list_t +{ + /** Number of attribute values in the list */ + uint32_t count; + + /** Attribute value list */ + tai_attribute_value_t *list; +} tai_attr_value_list_t; + /** * @brief Data Type * @@ -228,6 +241,7 @@ typedef union _tai_attribute_value_t tai_u32_range_t u32range; tai_s32_range_t s32range; tai_object_map_list_t objmaplist; + tai_attr_value_list_t attrlist; } tai_attribute_value_t; diff --git a/meta/main.py b/meta/main.py index ec27387..040ab2d 100644 --- a/meta/main.py +++ b/meta/main.py @@ -44,7 +44,7 @@ class TAIDefaultValueType(Enum): def process_type(header, type_): ts = [v.strip('#') for v in type_.split(' ')] - t = e = v = None + t = e = v = attrlistvaluetype = None if len(ts) == 1: t = ts[0] elif len(ts) == 2: @@ -53,6 +53,20 @@ def process_type(header, type_): e = ts[1] elif ts[0] == 'tai_pointer_t': t = ts[0] + elif ts[0] == 'tai_attr_value_list_t': + t = ts[0] + if ts[1] == 'tai_attr_value_list_t': + raise Exception("unsupported type format: {}".format(type_)) + attrlistvaluetype = ts[1] + else: + raise Exception("unsupported type format: {}".format(type_)) + elif len(ts) == 3: + if ts[0] == 'tai_attr_value_list_t': + t = ts[0] + if ts[1] == 'tai_attr_value_list_t': + raise Exception("unsupported type format: {}".format(type_)) + attrlistvaluetype = ts[1] + e = ts[2] else: raise Exception("unsupported type format: {}".format(type_)) else: @@ -66,10 +80,13 @@ def process_type(header, type_): e = t v = 's32' + if attrlistvaluetype: + attrlistvaluetype = header.attr_value_map.get(attrlistvaluetype, None) + if e and not header.get_enum(e): raise Exception("{} not found".format(e)) - return t, e, v + return t, e, v, attrlistvaluetype def process_default_value_type(default): @@ -126,7 +143,7 @@ class TAIAttribute(object): self.flags = set() # process type command t = self.cmt['type'] - self.type, self.enum_type, self.value_field = process_type(self.taiobject.taiheader, t) + self.type, self.enum_type, self.value_field, self.attrlist_value_type = process_type(self.taiobject.taiheader, t) # process default command self.default = self.cmt.get('default', '') @@ -191,8 +208,13 @@ class TAIHeader(object): return self._get_name(node, name) def _get_name(self, node, name): - if node.displayname == name: - return node + if node.displayname == name: + # ignore forward declaration + # https://joshpeterson.github.io/identifying-a-forward-declaration-with-libclang + d = node.get_definition() + c = clang.cindex.conf.lib.clang_getNullCursor() + if d != c and d == node: + return node for child in node.get_children(): n = self._get_name(child, name) if n: @@ -266,6 +288,9 @@ const tai_attr_metadata_t tai_metadata_attr_{{ typename }} = { .attridname = "{{ typename }}", .attridshortname = "{{ shorttypename }}", .attrvaluetype = {{ attr_type }}, +{%- if attrlist_value_type %} + .attrlistvaluetype = {{ attrlist_value_type }}, +{%- endif %} {%- if attr_flags %} .flags = {{ attr_flags }}, {%- else %} @@ -298,6 +323,9 @@ const tai_attr_metadata_t tai_metadata_attr_{{ typename }} = { raise Exception("invalid attr type name: {}, obj: {}".format(typename, obj)) shorttypename = typename[len(prefix):].lower().replace('_', '-') attr_type = 'TAI_ATTR_VALUE_TYPE_{}'.format(attr.value_field.upper()) + attrlist_value_type = None + if attr.attrlist_value_type: + attrlist_value_type = 'TAI_ATTR_VALUE_TYPE_{}'.format(attr.attrlist_value_type.upper()) is_enum = 'false' enum_meta_data = None if attr.enum_type: @@ -315,6 +343,7 @@ const tai_attr_metadata_t tai_metadata_attr_{{ typename }} = { 'typename': typename, 'shorttypename': shorttypename, 'attr_type': attr_type, + 'attrlist_value_type': attrlist_value_type, 'attr_flags': attr_flags, 'value_field': attr.value_field, 'is_enum': is_enum, diff --git a/meta/taimetadatatypes.h b/meta/taimetadatatypes.h index 552dc04..a20b282 100644 --- a/meta/taimetadatatypes.h +++ b/meta/taimetadatatypes.h @@ -45,6 +45,11 @@ */ typedef enum _tai_attr_value_type_t { + /** + * @brief Attribute value is unspecified + */ + TAI_ATTR_VALUE_TYPE_UNSPECIFIED, + /** * @brief Attribute value is bool. */ @@ -170,6 +175,11 @@ typedef enum _tai_attr_value_type_t */ TAI_ATTR_VALUE_TYPE_OBJMAPLIST, + /** + * @brief Attribute value is attr list. + */ + TAI_ATTR_VALUE_TYPE_ATTRLIST, + } tai_attr_value_type_t; /** @@ -475,6 +485,11 @@ typedef struct _tai_attr_metadata_t */ tai_attr_value_type_t attrvaluetype; + /** + * @brief Specifies internal attribute value type for attr list attribute. + */ + tai_attr_value_type_t attrlistvaluetype; + /** * @brief Specifies flags for this attribute. */ diff --git a/meta/taiserialize.c b/meta/taiserialize.c index 1566ebc..9218cbd 100644 --- a/meta/taiserialize.c +++ b/meta/taiserialize.c @@ -553,143 +553,169 @@ int tai_deserialize_enum( return tai_deserialize_int32(buffer, value); } -int tai_serialize_attribute( +int tai_serialize_attribute_value( _Out_ char *buffer, _In_ const tai_attr_metadata_t *meta, - _In_ const tai_attribute_t *attr, + _In_ const tai_attribute_value_t *value, _In_ const tai_serialize_option_t *option) { int i; char *ptr = buffer; - if ( option == NULL || !option->valueonly ) { - if ( option != NULL && option->human ) { - ptr += sprintf(ptr, "%s | ", meta->attridshortname); - } else { - ptr += sprintf(ptr, "%s | ", meta->attridname); - } - } + + tai_attr_metadata_t m = *meta; + m.attrvaluetype = meta->attrlistvaluetype; + m.attrlistvaluetype = TAI_ATTR_VALUE_TYPE_UNSPECIFIED; + switch ( meta->attrvaluetype ) { case TAI_ATTR_VALUE_TYPE_BOOLDATA: - return tai_serialize_bool(ptr, attr->value.booldata); + return tai_serialize_bool(ptr, value->booldata); case TAI_ATTR_VALUE_TYPE_CHARDATA: - return tai_serialize_chardata(ptr, attr->value.chardata); + return tai_serialize_chardata(ptr, value->chardata); case TAI_ATTR_VALUE_TYPE_U8: - return tai_serialize_uint8(ptr, attr->value.u8); + return tai_serialize_uint8(ptr, value->u8); case TAI_ATTR_VALUE_TYPE_S8: - return tai_serialize_int8(ptr, attr->value.s8); + return tai_serialize_int8(ptr, value->s8); case TAI_ATTR_VALUE_TYPE_U16: - return tai_serialize_uint16(ptr, attr->value.u16); + return tai_serialize_uint16(ptr, value->u16); case TAI_ATTR_VALUE_TYPE_S16: - return tai_serialize_int16(ptr, attr->value.s16); + return tai_serialize_int16(ptr, value->s16); case TAI_ATTR_VALUE_TYPE_U32: - return tai_serialize_uint32(ptr, attr->value.u32); + return tai_serialize_uint32(ptr, value->u32); case TAI_ATTR_VALUE_TYPE_S32: if ( meta->isenum ) { - return tai_serialize_enum(ptr, meta->enummetadata, attr->value.s32, option); + return tai_serialize_enum(ptr, meta->enummetadata, value->s32, option); } - return tai_serialize_int32(ptr, attr->value.s32); + return tai_serialize_int32(ptr, value->s32); case TAI_ATTR_VALUE_TYPE_U64: - return tai_serialize_uint64(ptr, attr->value.u64); + return tai_serialize_uint64(ptr, value->u64); case TAI_ATTR_VALUE_TYPE_S64: - return tai_serialize_int64(ptr, attr->value.s64); + return tai_serialize_int64(ptr, value->s64); case TAI_ATTR_VALUE_TYPE_FLT: - return tai_serialize_float(ptr, attr->value.flt); + return tai_serialize_float(ptr, value->flt); case TAI_ATTR_VALUE_TYPE_PTR: TAI_META_LOG_WARN("pointer serialization is not implemented"); return TAI_SERIALIZE_ERROR; case TAI_ATTR_VALUE_TYPE_OID: - return tai_serialize_object_id(ptr, attr->value.oid); + return tai_serialize_object_id(ptr, value->oid); case TAI_ATTR_VALUE_TYPE_OBJLIST: - for ( i = 0; i < attr->value.objlist.count; i++ ) { - ptr += tai_serialize_object_id(ptr, attr->value.objlist.list[i]); - if ( i + 1 < attr->value.objlist.count ) { + for ( i = 0; i < value->objlist.count; i++ ) { + ptr += tai_serialize_object_id(ptr, value->objlist.list[i]); + if ( i + 1 < value->objlist.count ) { ptr += sprintf(ptr, ","); } } return ptr - buffer; case TAI_ATTR_VALUE_TYPE_CHARLIST: - memcpy(ptr, attr->value.charlist.list, attr->value.charlist.count); - return ptr - buffer + attr->value.charlist.count; + memcpy(ptr, value->charlist.list, value->charlist.count); + return ptr - buffer + value->charlist.count; case TAI_ATTR_VALUE_TYPE_U8LIST: - for ( i = 0; i < attr->value.u8list.count; i++ ) { - ptr += tai_serialize_uint8(ptr, attr->value.u8list.list[i]); - if ( i + 1 < attr->value.u8list.count ) { + for ( i = 0; i < value->u8list.count; i++ ) { + ptr += tai_serialize_uint8(ptr, value->u8list.list[i]); + if ( i + 1 < value->u8list.count ) { ptr += sprintf(ptr, ","); } } return ptr - buffer; case TAI_ATTR_VALUE_TYPE_S8LIST: - for ( i = 0; i < attr->value.s8list.count; i++ ) { - ptr += tai_serialize_int8(ptr, attr->value.s8list.list[i]); - if ( i + 1 < attr->value.s8list.count ) { + for ( i = 0; i < value->s8list.count; i++ ) { + ptr += tai_serialize_int8(ptr, value->s8list.list[i]); + if ( i + 1 < value->s8list.count ) { ptr += sprintf(ptr, ","); } } return ptr - buffer; case TAI_ATTR_VALUE_TYPE_U16LIST: - for ( i = 0; i < attr->value.u16list.count; i++ ) { - ptr += tai_serialize_uint16(ptr, attr->value.u16list.list[i]); - if ( i + 1 < attr->value.u16list.count ) { + for ( i = 0; i < value->u16list.count; i++ ) { + ptr += tai_serialize_uint16(ptr, value->u16list.list[i]); + if ( i + 1 < value->u16list.count ) { ptr += sprintf(ptr, ","); } } return ptr - buffer; case TAI_ATTR_VALUE_TYPE_S16LIST: - for ( i = 0; i < attr->value.s16list.count; i++ ) { - ptr += tai_serialize_int16(ptr, attr->value.s16list.list[i]); - if ( i + 1 < attr->value.s16list.count ) { + for ( i = 0; i < value->s16list.count; i++ ) { + ptr += tai_serialize_int16(ptr, value->s16list.list[i]); + if ( i + 1 < value->s16list.count ) { ptr += sprintf(ptr, ","); } } return ptr - buffer; case TAI_ATTR_VALUE_TYPE_U32LIST: - for ( i = 0; i < attr->value.u32list.count; i++ ) { - ptr += tai_serialize_uint32(ptr, attr->value.u32list.list[i]); - if ( i + 1 < attr->value.u32list.count ) { + for ( i = 0; i < value->u32list.count; i++ ) { + ptr += tai_serialize_uint32(ptr, value->u32list.list[i]); + if ( i + 1 < value->u32list.count ) { ptr += sprintf(ptr, ","); } } return ptr - buffer; case TAI_ATTR_VALUE_TYPE_S32LIST: if ( meta->isenum ) { - for ( i = 0; i < attr->value.s32list.count; i++ ) { - ptr += tai_serialize_enum(ptr, meta->enummetadata, attr->value.s32list.list[i], option); - if ( i + 1 < attr->value.s32list.count ) { + for ( i = 0; i < value->s32list.count; i++ ) { + ptr += tai_serialize_enum(ptr, meta->enummetadata, value->s32list.list[i], option); + if ( i + 1 < value->s32list.count ) { ptr += sprintf(ptr, "|"); } } return ptr - buffer; } - for ( i = 0; i < attr->value.s32list.count; i++ ) { - ptr += tai_serialize_int32(ptr, attr->value.s32list.list[i]); - if ( i + 1 < attr->value.s32list.count ) { + for ( i = 0; i < value->s32list.count; i++ ) { + ptr += tai_serialize_int32(ptr, value->s32list.list[i]); + if ( i + 1 < value->s32list.count ) { ptr += sprintf(ptr, ","); } } return ptr - buffer; case TAI_ATTR_VALUE_TYPE_FLOATLIST: - for ( i = 0; i < attr->value.floatlist.count; i++ ) { - ptr += tai_serialize_float(ptr, attr->value.floatlist.list[i]); - if ( i + 1 < attr->value.floatlist.count ) { + for ( i = 0; i < value->floatlist.count; i++ ) { + ptr += tai_serialize_float(ptr, value->floatlist.list[i]); + if ( i + 1 < value->floatlist.count ) { ptr += sprintf(ptr, ","); } } return ptr - buffer; case TAI_ATTR_VALUE_TYPE_U32RANGE: - ptr += sprintf(ptr, "%u..%u", attr->value.u32range.min, attr->value.u32range.max); + ptr += sprintf(ptr, "%u..%u", value->u32range.min, value->u32range.max); return ptr - buffer; case TAI_ATTR_VALUE_TYPE_S32RANGE: - ptr += sprintf(ptr, "%d..%d", attr->value.s32range.min, attr->value.s32range.max); + ptr += sprintf(ptr, "%d..%d", value->s32range.min, value->s32range.max); return ptr - buffer; case TAI_ATTR_VALUE_TYPE_OBJMAPLIST: TAI_META_LOG_WARN("objmaplist serialization is not implemented"); return TAI_SERIALIZE_ERROR; + case TAI_ATTR_VALUE_TYPE_ATTRLIST: + for ( i = 0; i < value->attrlist.count; i++ ) { + ptr += tai_serialize_attribute_value(ptr, &m, &value->attrlist.list[i], option); + if ( i != (value->attrlist.count - 1)) { + ptr += sprintf(ptr, ", "); + } + } + return ptr - buffer; default: TAI_META_LOG_WARN("unknown attr value type"); } return TAI_SERIALIZE_ERROR; } +int tai_serialize_attribute( + _Out_ char *buffer, + _In_ const tai_attr_metadata_t *meta, + _In_ const tai_attribute_t *attr, + _In_ const tai_serialize_option_t *option) +{ + char *ptr = buffer; + int count = 0; + if ( option == NULL || !option->valueonly ) { + if ( option != NULL && option->human ) { + ptr += sprintf(ptr, "%s | ", meta->attridshortname); + } else { + ptr += sprintf(ptr, "%s | ", meta->attridname); + } + count = ptr - buffer; + } + + return count + tai_serialize_attribute_value(ptr, meta, &attr->value, option); +} + int tai_deserialize_attribute( _In_ const char *buffer, _In_ const tai_attr_metadata_t *meta,