#ifndef BABELTRACE_CTF_WRITER_FIELDS_INTERNAL_H #define BABELTRACE_CTF_WRITER_FIELDS_INTERNAL_H /* * Copyright 2013, 2014 Jérémie Galarneau * * Author: Jérémie Galarneau * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * The Common Trace Format (CTF) Specification is available at * http://www.efficios.com/ctf */ #include #include #include #include #include #include #include #include #include "common/macros.h" #include "common/common.h" #include "ctfser/ctfser.h" #include "assert-pre.h" #include "field-types.h" #include "object.h" #include "utils.h" #define BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(_field, _type_id, _name) \ BT_CTF_ASSERT_PRE((_field)->type->id == ((int) (_type_id)), \ _name " has the wrong type ID: expected-type-id=%s, " \ "field-addr=%p", \ bt_ctf_field_type_id_string((int) (_type_id)), (_field)) #define BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(_field, _name) \ BT_CTF_ASSERT_PRE(bt_ctf_field_common_is_set_recursive(_field), \ _name " is not set: field-addr=%p", (_field)) #define BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(_field, _name) \ BT_CTF_ASSERT_PRE_HOT((_field), (_name), ": field-addr=%p", (_field)) struct bt_ctf_field_common; typedef void (*bt_ctf_field_common_method_set_is_frozen)(struct bt_ctf_field_common *, bool); typedef int (*bt_ctf_field_common_method_validate)(struct bt_ctf_field_common *); typedef struct bt_ctf_field_common *(*bt_ctf_field_common_method_copy)( struct bt_ctf_field_common *); typedef bt_ctf_bool (*bt_ctf_field_common_method_is_set)(struct bt_ctf_field_common *); typedef void (*bt_ctf_field_common_method_reset)(struct bt_ctf_field_common *); struct bt_ctf_field_common_methods { bt_ctf_field_common_method_set_is_frozen set_is_frozen; bt_ctf_field_common_method_validate validate; bt_ctf_field_common_method_copy copy; bt_ctf_field_common_method_is_set is_set; bt_ctf_field_common_method_reset reset; }; struct bt_ctf_field_common { struct bt_ctf_object base; struct bt_ctf_field_type_common *type; struct bt_ctf_field_common_methods *methods; bool payload_set; bool frozen; /* * Specialized data for either CTF IR or CTF writer APIs. * See comment in `field-types.h` for more details. */ union { struct { } ir; struct { void *serialize_func; } writer; } spec; }; struct bt_ctf_field_common_integer { struct bt_ctf_field_common common; union { int64_t signd; uint64_t unsignd; } payload; }; struct bt_ctf_field_common_floating_point { struct bt_ctf_field_common common; double payload; }; struct bt_ctf_field_common_structure { struct bt_ctf_field_common common; /* Array of `struct bt_ctf_field_common *`, owned by this */ GPtrArray *fields; }; struct bt_ctf_field_common_variant { struct bt_ctf_field_common common; union { uint64_t u; int64_t i; } tag_value; /* Weak: belongs to `choices` below */ struct bt_ctf_field_common *current_field; /* Array of `struct bt_ctf_field_common *`, owned by this */ GPtrArray *fields; }; struct bt_ctf_field_common_array { struct bt_ctf_field_common common; /* Array of `struct bt_ctf_field_common *`, owned by this */ GPtrArray *elements; }; struct bt_ctf_field_common_sequence { struct bt_ctf_field_common common; /* * This is the true sequence field's length: its value can be * less than `elements->len` below because we never shrink the * array of elements to avoid reallocation. */ uint64_t length; /* Array of `struct bt_ctf_field_common *`, owned by this */ GPtrArray *elements; }; struct bt_ctf_field_common_string { struct bt_ctf_field_common common; GArray *buf; size_t size; }; BT_HIDDEN struct bt_ctf_field_common *bt_ctf_field_common_copy(struct bt_ctf_field_common *field); BT_HIDDEN int bt_ctf_field_common_structure_initialize(struct bt_ctf_field_common *field, struct bt_ctf_field_type_common *type, bool is_shared, bt_ctf_object_release_func release_func, struct bt_ctf_field_common_methods *methods, bt_ctf_field_common_create_func field_create_func, GDestroyNotify field_release_func); BT_HIDDEN int bt_ctf_field_common_array_initialize(struct bt_ctf_field_common *field, struct bt_ctf_field_type_common *type, bool is_shared, bt_ctf_object_release_func release_func, struct bt_ctf_field_common_methods *methods, bt_ctf_field_common_create_func field_create_func, GDestroyNotify field_destroy_func); BT_HIDDEN int bt_ctf_field_common_sequence_initialize(struct bt_ctf_field_common *field, struct bt_ctf_field_type_common *type, bool is_shared, bt_ctf_object_release_func release_func, struct bt_ctf_field_common_methods *methods, GDestroyNotify field_destroy_func); BT_HIDDEN int bt_ctf_field_common_variant_initialize(struct bt_ctf_field_common *field, struct bt_ctf_field_type_common *type, bool is_shared, bt_ctf_object_release_func release_func, struct bt_ctf_field_common_methods *methods, bt_ctf_field_common_create_func field_create_func, GDestroyNotify field_release_func); BT_HIDDEN int bt_ctf_field_common_string_initialize(struct bt_ctf_field_common *field, struct bt_ctf_field_type_common *type, bool is_shared, bt_ctf_object_release_func release_func, struct bt_ctf_field_common_methods *methods); BT_HIDDEN int bt_ctf_field_common_generic_validate(struct bt_ctf_field_common *field); BT_HIDDEN int bt_ctf_field_common_structure_validate_recursive(struct bt_ctf_field_common *field); BT_HIDDEN int bt_ctf_field_common_variant_validate_recursive(struct bt_ctf_field_common *field); BT_HIDDEN int bt_ctf_field_common_array_validate_recursive(struct bt_ctf_field_common *field); BT_HIDDEN int bt_ctf_field_common_sequence_validate_recursive(struct bt_ctf_field_common *field); BT_HIDDEN void bt_ctf_field_common_generic_reset(struct bt_ctf_field_common *field); BT_HIDDEN void bt_ctf_field_common_structure_reset_recursive(struct bt_ctf_field_common *field); BT_HIDDEN void bt_ctf_field_common_variant_reset_recursive(struct bt_ctf_field_common *field); BT_HIDDEN void bt_ctf_field_common_array_reset_recursive(struct bt_ctf_field_common *field); BT_HIDDEN void bt_ctf_field_common_sequence_reset_recursive(struct bt_ctf_field_common *field); BT_HIDDEN void bt_ctf_field_common_generic_set_is_frozen(struct bt_ctf_field_common *field, bool is_frozen); BT_HIDDEN void bt_ctf_field_common_structure_set_is_frozen_recursive( struct bt_ctf_field_common *field, bool is_frozen); BT_HIDDEN void bt_ctf_field_common_variant_set_is_frozen_recursive( struct bt_ctf_field_common *field, bool is_frozen); BT_HIDDEN void bt_ctf_field_common_array_set_is_frozen_recursive( struct bt_ctf_field_common *field, bool is_frozen); BT_HIDDEN void bt_ctf_field_common_sequence_set_is_frozen_recursive( struct bt_ctf_field_common *field, bool is_frozen); BT_HIDDEN void _bt_ctf_field_common_set_is_frozen_recursive(struct bt_ctf_field_common *field, bool is_frozen); BT_HIDDEN bt_ctf_bool bt_ctf_field_common_generic_is_set(struct bt_ctf_field_common *field); BT_HIDDEN bt_ctf_bool bt_ctf_field_common_structure_is_set_recursive( struct bt_ctf_field_common *field); BT_HIDDEN bt_ctf_bool bt_ctf_field_common_variant_is_set_recursive(struct bt_ctf_field_common *field); BT_HIDDEN bt_ctf_bool bt_ctf_field_common_array_is_set_recursive(struct bt_ctf_field_common *field); BT_HIDDEN bt_ctf_bool bt_ctf_field_common_sequence_is_set_recursive(struct bt_ctf_field_common *field); #ifdef BT_DEV_MODE # define bt_ctf_field_common_validate_recursive _bt_ctf_field_common_validate_recursive # define bt_ctf_field_common_set_is_frozen_recursive _bt_ctf_field_common_set_is_frozen_recursive # define bt_ctf_field_common_is_set_recursive _bt_ctf_field_common_is_set_recursive # define bt_ctf_field_common_reset_recursive _bt_ctf_field_common_reset_recursive # define bt_ctf_field_common_set _bt_ctf_field_common_set #else # define bt_ctf_field_common_validate_recursive(_field) (-1) # define bt_ctf_field_common_set_is_frozen_recursive(_field, _is_frozen) # define bt_ctf_field_common_is_set_recursive(_field) (BT_CTF_FALSE) # define bt_ctf_field_common_reset_recursive(_field) # define bt_ctf_field_common_set(_field, _val) #endif BT_ASSERT_DBG_FUNC static inline bool field_type_common_has_known_id( struct bt_ctf_field_type_common *ft) { return (int) ft->id > BT_CTF_FIELD_TYPE_ID_UNKNOWN && (int) ft->id < BT_CTF_FIELD_TYPE_ID_NR; } static inline int _bt_ctf_field_common_validate_recursive(struct bt_ctf_field_common *field) { int ret = 0; if (!field) { BT_CTF_ASSERT_PRE_MSG("%s", "Invalid field: field is NULL."); ret = -1; goto end; } BT_ASSERT_DBG(field_type_common_has_known_id(field->type)); if (field->methods->validate) { ret = field->methods->validate(field); } end: return ret; } static inline void _bt_ctf_field_common_reset_recursive(struct bt_ctf_field_common *field) { BT_ASSERT_DBG(field); BT_ASSERT_DBG(field->methods->reset); field->methods->reset(field); } static inline void _bt_ctf_field_common_set(struct bt_ctf_field_common *field, bool value) { BT_ASSERT_DBG(field); field->payload_set = value; } static inline bt_ctf_bool _bt_ctf_field_common_is_set_recursive(struct bt_ctf_field_common *field) { bt_ctf_bool is_set = BT_CTF_FALSE; if (!field) { goto end; } BT_ASSERT_DBG(field_type_common_has_known_id(field->type)); BT_ASSERT_DBG(field->methods->is_set); is_set = field->methods->is_set(field); end: return is_set; } static inline void bt_ctf_field_common_initialize(struct bt_ctf_field_common *field, struct bt_ctf_field_type_common *ft, bool is_shared, bt_ctf_object_release_func release_func, struct bt_ctf_field_common_methods *methods) { BT_ASSERT_DBG(field); BT_ASSERT_DBG(ft); bt_ctf_object_init(&field->base, is_shared, release_func); field->methods = methods; field->type = (void *) bt_ctf_object_get_ref(ft); } static inline struct bt_ctf_field_type_common *bt_ctf_field_common_borrow_type( struct bt_ctf_field_common *field) { struct bt_ctf_field_type_common *ret = NULL; BT_CTF_ASSERT_PRE_NON_NULL(field, "Field"); ret = field->type; return ret; } static inline int64_t bt_ctf_field_common_sequence_get_length(struct bt_ctf_field_common *field) { struct bt_ctf_field_common_sequence *sequence = BT_CTF_FROM_COMMON(field); BT_CTF_ASSERT_PRE_NON_NULL(field, "Sequence field"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_SEQUENCE, "Field"); return (int64_t) sequence->length; } static inline int bt_ctf_field_common_sequence_set_length(struct bt_ctf_field_common *field, uint64_t length, bt_ctf_field_common_create_func field_create_func) { int ret = 0; struct bt_ctf_field_common_sequence *sequence = BT_CTF_FROM_COMMON(field); BT_CTF_ASSERT_PRE_NON_NULL(field, "Sequence field"); BT_CTF_ASSERT_PRE(((int64_t) length) >= 0, "Invalid sequence length (too large): length=%" PRId64, length); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "Sequence field"); if (G_UNLIKELY(length > sequence->elements->len)) { /* Make more room */ struct bt_ctf_field_type_common_sequence *sequence_ft; uint64_t cur_len = sequence->elements->len; uint64_t i; g_ptr_array_set_size(sequence->elements, length); sequence_ft = BT_CTF_FROM_COMMON(sequence->common.type); for (i = cur_len; i < sequence->elements->len; i++) { struct bt_ctf_field_common *elem_field = field_create_func(sequence_ft->element_ft); if (!elem_field) { ret = -1; goto end; } BT_ASSERT_DBG(!sequence->elements->pdata[i]); sequence->elements->pdata[i] = elem_field; } } sequence->length = length; end: return ret; } static inline struct bt_ctf_field_common *bt_ctf_field_common_structure_borrow_field_by_name( struct bt_ctf_field_common *field, const char *name) { struct bt_ctf_field_common *ret = NULL; GQuark field_quark; struct bt_ctf_field_type_common_structure *structure_ft; struct bt_ctf_field_common_structure *structure = BT_CTF_FROM_COMMON(field); size_t index; GHashTable *field_name_to_index; BT_CTF_ASSERT_PRE_NON_NULL(field, "Structure field"); BT_CTF_ASSERT_PRE_NON_NULL(name, "Field name"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_STRUCT, "Field"); structure_ft = BT_CTF_FROM_COMMON(field->type); field_name_to_index = structure_ft->field_name_to_index; field_quark = g_quark_from_string(name); if (!g_hash_table_lookup_extended(field_name_to_index, GUINT_TO_POINTER(field_quark), NULL, (gpointer *) &index)) { BT_LOGT("Invalid parameter: no such field in structure field's type: " "struct-field-addr=%p, struct-ft-addr=%p, name=\"%s\"", field, field->type, name); goto error; } ret = structure->fields->pdata[index]; BT_ASSERT_DBG(ret); error: return ret; } static inline struct bt_ctf_field_common *bt_ctf_field_common_structure_borrow_field_by_index( struct bt_ctf_field_common *field, uint64_t index) { struct bt_ctf_field_common_structure *structure = BT_CTF_FROM_COMMON(field); BT_CTF_ASSERT_PRE_NON_NULL(field, "Structure field"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_STRUCT, "Field"); BT_CTF_ASSERT_PRE(index < structure->fields->len, "Index is out of bound: struct-field-addr=%p, " "index=%" PRIu64 ", count=%u", field, index, structure->fields->len); return structure->fields->pdata[index]; } static inline struct bt_ctf_field_common *bt_ctf_field_common_array_borrow_field( struct bt_ctf_field_common *field, uint64_t index) { struct bt_ctf_field_common_array *array = BT_CTF_FROM_COMMON(field); BT_CTF_ASSERT_PRE_NON_NULL(field, "Array field"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_ARRAY, "Field"); BT_CTF_ASSERT_PRE(index < array->elements->len, "Index is out of bound: array-field-addr=%p, " "index=%" PRIu64 ", count=%u", field, index, array->elements->len); return array->elements->pdata[(size_t) index]; } static inline struct bt_ctf_field_common *bt_ctf_field_common_sequence_borrow_field( struct bt_ctf_field_common *field, uint64_t index) { struct bt_ctf_field_common_sequence *sequence = BT_CTF_FROM_COMMON(field); BT_CTF_ASSERT_PRE_NON_NULL(field, "Sequence field"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_SEQUENCE, "Field"); BT_CTF_ASSERT_PRE(index < sequence->length, "Index is out of bound: seq-field-addr=%p, " "index=%" PRIu64 ", count=%u", field, index, sequence->elements->len); return sequence->elements->pdata[(size_t) index]; } static inline int bt_ctf_field_common_variant_set_tag(struct bt_ctf_field_common *variant_field, uint64_t tag_uval, bool is_signed) { int ret = 0; int64_t choice_index; struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(variant_field); BT_CTF_ASSERT_PRE_NON_NULL(variant_field, "Variant field"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(variant_field, BT_CTF_FIELD_TYPE_ID_VARIANT, "Field"); /* Find matching index in variant field's type */ choice_index = bt_ctf_field_type_common_variant_find_choice_index( variant_field->type, tag_uval, is_signed); if (choice_index < 0) { ret = -1; goto end; } /* Select corresponding field */ BT_ASSERT_DBG(choice_index < variant->fields->len); variant->current_field = variant->fields->pdata[choice_index]; variant->tag_value.u = tag_uval; end: return ret; } static inline struct bt_ctf_field_common *bt_ctf_field_common_variant_borrow_current_field( struct bt_ctf_field_common *variant_field) { struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(variant_field); BT_CTF_ASSERT_PRE_NON_NULL(variant_field, "Variant field"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(variant_field, BT_CTF_FIELD_TYPE_ID_VARIANT, "Field"); BT_CTF_ASSERT_PRE(variant->current_field, "Variant field has no current field: field-addr=%p", variant_field); return variant->current_field; } static inline int bt_ctf_field_common_variant_get_tag_signed(struct bt_ctf_field_common *variant_field, int64_t *tag) { struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(variant_field); BT_CTF_ASSERT_PRE_NON_NULL(variant_field, "Variant field"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(variant_field, BT_CTF_FIELD_TYPE_ID_VARIANT, "Field"); BT_CTF_ASSERT_PRE(variant->current_field, "Variant field has no current field: field-addr=%p", variant_field); *tag = variant->tag_value.i; return 0; } static inline int bt_ctf_field_common_variant_get_tag_unsigned(struct bt_ctf_field_common *variant_field, uint64_t *tag) { struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(variant_field); BT_CTF_ASSERT_PRE_NON_NULL(variant_field, "Variant field"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(variant_field, BT_CTF_FIELD_TYPE_ID_VARIANT, "Field"); BT_CTF_ASSERT_PRE(variant->current_field, "Variant field has no current field: field-addr=%p", variant_field); *tag = variant->tag_value.u; return 0; } static inline int bt_ctf_field_common_floating_point_get_value(struct bt_ctf_field_common *field, double *value) { struct bt_ctf_field_common_floating_point *floating_point = BT_CTF_FROM_COMMON(field); BT_CTF_ASSERT_PRE_NON_NULL(field, "Floating point number field"); BT_CTF_ASSERT_PRE_NON_NULL(value, "Value"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(field, "Floating point number field"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_FLOAT, "Field"); *value = floating_point->payload; return 0; } static inline int bt_ctf_field_common_floating_point_set_value(struct bt_ctf_field_common *field, double value) { struct bt_ctf_field_common_floating_point *floating_point = BT_CTF_FROM_COMMON(field); BT_CTF_ASSERT_PRE_NON_NULL(field, "Floating point number field"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "Floating point number field"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_FLOAT, "Field"); floating_point->payload = value; bt_ctf_field_common_set(field, true); return 0; } static inline const char *bt_ctf_field_common_string_get_value(struct bt_ctf_field_common *field) { struct bt_ctf_field_common_string *string = BT_CTF_FROM_COMMON(field); BT_CTF_ASSERT_PRE_NON_NULL(field, "String field"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(field, "String field"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_STRING, "Field"); return (const char *) string->buf->data; } static inline int bt_ctf_field_common_string_clear(struct bt_ctf_field_common *field) { struct bt_ctf_field_common_string *string_field = BT_CTF_FROM_COMMON(field); BT_CTF_ASSERT_PRE_NON_NULL(field, "String field"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "String field"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_STRING, "Field"); string_field->size = 0; bt_ctf_field_common_set(field, true); return 0; } static inline int bt_ctf_field_common_string_append_len(struct bt_ctf_field_common *field, const char *value, unsigned int length) { struct bt_ctf_field_common_string *string_field = BT_CTF_FROM_COMMON(field); char *data; size_t new_size; BT_CTF_ASSERT_PRE_NON_NULL(field, "String field"); BT_CTF_ASSERT_PRE_NON_NULL(value, "Value"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "String field"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_STRING, "Field"); /* Make sure no null bytes are appended */ BT_CTF_ASSERT_PRE(!memchr(value, '\0', length), "String value to append contains a null character: " "partial-value=\"%.32s\", length=%u", value, length); new_size = string_field->size + length; if (G_UNLIKELY(new_size + 1 > string_field->buf->len)) { g_array_set_size(string_field->buf, new_size + 1); } data = string_field->buf->data; memcpy(data + string_field->size, value, length); ((char *) string_field->buf->data)[new_size] = '\0'; string_field->size = new_size; bt_ctf_field_common_set(field, true); return 0; } static inline int bt_ctf_field_common_string_append(struct bt_ctf_field_common *field, const char *value) { BT_CTF_ASSERT_PRE_NON_NULL(value, "Value"); return bt_ctf_field_common_string_append_len(field, value, strlen(value)); } static inline int bt_ctf_field_common_string_set_value(struct bt_ctf_field_common *field, const char *value) { BT_CTF_ASSERT_PRE_NON_NULL(field, "String field"); BT_CTF_ASSERT_PRE_NON_NULL(value, "Value"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "String field"); BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_STRING, "Field"); bt_ctf_field_common_string_clear(field); return bt_ctf_field_common_string_append_len(field, value, strlen(value)); } static inline void bt_ctf_field_common_finalize(struct bt_ctf_field_common *field) { BT_ASSERT_DBG(field); BT_LOGD_STR("Putting field's type."); bt_ctf_object_put_ref(field->type); } static inline void bt_ctf_field_common_integer_finalize(struct bt_ctf_field_common *field) { BT_ASSERT_DBG(field); BT_LOGD("Finalizing common integer field object: addr=%p", field); bt_ctf_field_common_finalize(field); } static inline void bt_ctf_field_common_floating_point_finalize(struct bt_ctf_field_common *field) { BT_ASSERT_DBG(field); BT_LOGD("Finalizing common floating point number field object: addr=%p", field); bt_ctf_field_common_finalize(field); } static inline void bt_ctf_field_common_structure_finalize_recursive(struct bt_ctf_field_common *field) { struct bt_ctf_field_common_structure *structure = BT_CTF_FROM_COMMON(field); BT_ASSERT_DBG(field); BT_LOGD("Finalizing common structure field object: addr=%p", field); bt_ctf_field_common_finalize(field); if (structure->fields) { g_ptr_array_free(structure->fields, TRUE); } } static inline void bt_ctf_field_common_variant_finalize_recursive(struct bt_ctf_field_common *field) { struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(field); BT_ASSERT_DBG(field); BT_LOGD("Finalizing common variant field object: addr=%p", field); bt_ctf_field_common_finalize(field); if (variant->fields) { g_ptr_array_free(variant->fields, TRUE); } } static inline void bt_ctf_field_common_array_finalize_recursive(struct bt_ctf_field_common *field) { struct bt_ctf_field_common_array *array = BT_CTF_FROM_COMMON(field); BT_ASSERT_DBG(field); BT_LOGD("Finalizing common array field object: addr=%p", field); bt_ctf_field_common_finalize(field); if (array->elements) { g_ptr_array_free(array->elements, TRUE); } } static inline void bt_ctf_field_common_sequence_finalize_recursive(struct bt_ctf_field_common *field) { struct bt_ctf_field_common_sequence *sequence = BT_CTF_FROM_COMMON(field); BT_ASSERT_DBG(field); BT_LOGD("Finalizing common sequence field object: addr=%p", field); bt_ctf_field_common_finalize(field); if (sequence->elements) { g_ptr_array_free(sequence->elements, TRUE); } } static inline void bt_ctf_field_common_string_finalize(struct bt_ctf_field_common *field) { struct bt_ctf_field_common_string *string = BT_CTF_FROM_COMMON(field); BT_ASSERT_DBG(field); BT_LOGD("Finalizing common string field object: addr=%p", field); bt_ctf_field_common_finalize(field); if (string->buf) { g_array_free(string->buf, TRUE); } } BT_CTF_ASSERT_PRE_FUNC static inline bool value_is_in_range_signed(unsigned int size, int64_t value) { bool ret = true; int64_t min_value, max_value; min_value = -(1ULL << (size - 1)); max_value = (1ULL << (size - 1)) - 1; if (value < min_value || value > max_value) { BT_LOGF("Value is out of bounds: value=%" PRId64 ", " "min-value=%" PRId64 ", max-value=%" PRId64, value, min_value, max_value); ret = false; } return ret; } BT_CTF_ASSERT_PRE_FUNC static inline bool value_is_in_range_unsigned(unsigned int size, uint64_t value) { bool ret = true; int64_t max_value; max_value = (size == 64) ? UINT64_MAX : ((uint64_t) 1 << size) - 1; if (value > max_value) { BT_LOGF("Value is out of bounds: value=%" PRIu64 ", " "max-value=%" PRIu64, value, max_value); ret = false; } return ret; } struct bt_ctf_field_enumeration { struct bt_ctf_field_common common; struct bt_ctf_field_common_integer *container; }; struct bt_ctf_field_variant { struct bt_ctf_field_common_variant common; struct bt_ctf_field_enumeration *tag; }; BT_HIDDEN int bt_ctf_field_serialize_recursive(struct bt_ctf_field *field, struct bt_ctfser *ctfser, enum bt_ctf_byte_order native_byte_order); BT_HIDDEN int bt_ctf_field_structure_set_field_by_name(struct bt_ctf_field *field, const char *name, struct bt_ctf_field *value); BT_HIDDEN struct bt_ctf_field *bt_ctf_field_enumeration_borrow_container( struct bt_ctf_field *field); static inline bt_ctf_bool bt_ctf_field_is_set_recursive(struct bt_ctf_field *field) { return bt_ctf_field_common_is_set_recursive((void *) field); } #endif /* BABELTRACE_CTF_WRITER_FIELDS_INTERNAL_H */