/** * Checks whether a set of offsets can be used for cstruct. * * Because cstruct does not support customizable offset (use struct for * that), this function can be used to check that offsets are compatible with * cstruct. * * \param field_count The number of array entries in `field_types` and `field_offsets` * \param field_types An array of the field types. * \param field_offsets The offsets corresponding to the types. * \param total_size The total size of the struct in bytes. * * \returns True if constructing a cstruct with the same types and field offsets will * produce the provided offsets. */ inline bool is_cstruct_compatible_offsets(size_t field_count, const ndt::type *field_types, const uintptr_t *field_offsets, size_t total_size) { size_t offset = 0, max_alignment = 1; for (size_t i = 0; i != field_count; ++i) { uintptr_t field_data_alignment = field_types[i].get_data_alignment(); uintptr_t field_data_size = field_types[i].get_data_size(); offset = inc_to_alignment(offset, field_data_alignment); if (field_offsets[i] != offset || field_data_size == 0) { return false; } max_alignment = (field_data_alignment > max_alignment) ? field_data_alignment : max_alignment; offset += field_data_size; } offset = inc_to_alignment(offset, max_alignment); return total_size == offset; }
/** * Fills in the array of default data offsets based on the data sizes * and alignments of the types. */ static void fill_default_data_offsets(intptr_t nfields, const type *field_tps, uintptr_t *out_data_offsets) { if (nfields > 0) { out_data_offsets[0] = 0; size_t offs = 0; for (intptr_t i = 1; i < nfields; ++i) { offs += field_tps[i - 1].get_default_data_size(); offs = inc_to_alignment(offs, field_tps[i].get_data_alignment()); out_data_offsets[i] = offs; } } }