/** @file SiSizes.cpp @brief Sizes estimation and calculation @details Copyright (c) 2019 Acronis International GmbH @author Denis Kopyrin ([email protected]) @since $Id: $ */ #pragma once #include "compat.h" #include "si_fp_properties.h" static inline int roundUp(int numToRound, int multiple) { return (numToRound + multiple - 1) & -multiple; } static const uint8_t k_fp_si_property_to_type[] = { #define SI_FP_PROP(prop, propPub, vt, type, name) vt, #define SI_FP_PROP_SIZED(...) SI_FP_PROP(__VA_ARGS__) #define SI_FP_PROP_HANDLE(...) SI_FP_PROP(__VA_ARGS__) #include "si_fp_properties_x.h" #undef SI_FP_PROP_HANDLE #undef SI_FP_PROP_SIZED #undef SI_FP_PROP }; static inline fp_si_property_value_type_t fp_si_property_id_to_fp_value_type(fp_si_property_id_t id) { #ifdef KERNEL_MOCK _Static_assert(sizeof(k_fp_si_property_to_type) / sizeof(*k_fp_si_property_to_type) == FP_SI_PI_MAX_PROPERTY_ID, "k_fp_si_property_to_type size mismatch"); #endif return (fp_si_property_value_type_t) k_fp_si_property_to_type[id]; } // From fp_si_property_id_t to SiPropertyId static const uint16_t k_fp_si_property_type_to_public_type[] = { #define SI_FP_PROP(prop, propPub, vt, type, name) propPub, #define SI_FP_PROP_SIZED(...) SI_FP_PROP(__VA_ARGS__) #define SI_FP_PROP_HANDLE(...) SI_FP_PROP(__VA_ARGS__) #include "si_fp_properties_x.h" #undef SI_FP_PROP_HANDLE #undef SI_FP_PROP_SIZED #undef SI_FP_PROP }; static inline SiPropertyId fp_si_property_id_to_public_type(fp_si_property_id_t id) { #ifdef KERNEL_MOCK _Static_assert(sizeof(k_fp_si_property_type_to_public_type) / sizeof(*k_fp_si_property_type_to_public_type) == FP_SI_PI_MAX_PROPERTY_ID, "k_fp_si_property_type_to_public_type size mismatch"); #endif return (SiPropertyId) k_fp_si_property_type_to_public_type[id]; } // Means that by default varsized fields do not add anything // It is expected that user will provide the proper size #define SI_LEN_VARSIZE 0 // From fp_si_property_value_type_t to size static const uint32_t k_fp_si_value_type_to_size[] = { #define SI_FP_VALUE(type, typePub, sz) sz, #include "si_fp_value_types_x.h" #undef SI_FP_VALUE }; static inline uint32_t fp_si_property_value_type_to_size(fp_si_property_value_type_t type) { #ifdef KERNEL_MOCK _Static_assert(sizeof(k_fp_si_value_type_to_size) / sizeof(*k_fp_si_value_type_to_size) == FP_SI_VT_MAX_PROPERTY_VALUE_TYPE, "k_fp_si_value_type_to_size size mismatch"); #endif return k_fp_si_value_type_to_size[type]; } // From fp_si_property_value_type_t to SiPropertyValueType static const uint8_t k_fp_si_value_type_to_public_type[] = { #define SI_FP_VALUE(type, typePub, sz) typePub, #include "si_fp_value_types_x.h" #undef SI_FP_VALUE }; static inline SiPropertyValueType fp_si_property_value_type_to_public_type(fp_si_property_value_type_t type) { #ifdef KERNEL_MOCK _Static_assert(sizeof(k_fp_si_value_type_to_public_type) / sizeof(*k_fp_si_value_type_to_public_type) == FP_SI_VT_MAX_PROPERTY_VALUE_TYPE, "k_fp_si_value_type_to_public_type size mismatch"); #endif return (SiPropertyValueType) k_fp_si_value_type_to_public_type[type]; } static inline bool si_property_value_type_wants_vector_wrap(SiPropertyValueType type) { return type == SI_VT_BYTE_ARRAY_TYPE || type == SI_VT_UTF8_STRING_TYPE; } static inline uint32_t si_estimate_property_size(fp_si_property_id_t prop_id) { fp_si_property_value_type_t value_type = fp_si_property_id_to_fp_value_type(prop_id); SiPropertyValueType value_type_pub = fp_si_property_value_type_to_public_type(value_type); size_t size = fp_si_property_value_type_to_size(value_type); // Any varsized data is stored inside SiVector, reserve space for that if (si_property_value_type_wants_vector_wrap(value_type_pub)) size += sizeof(SiVector); return size + sizeof(SiProperty); } // I am not sure compiler is going to be able to inline this but I can only hope it can static inline uint32_t si_estimate_size(const uint8_t* params, size_t paramsNumber) { uint32_t est = 0; size_t i; for (i = 0; i < paramsNumber; i++) { est += si_estimate_property_size(params[i]); } return roundUp(est, 8); } #define SI_ESTIMATE_SIZE_CONST_PARAMS(params) si_estimate_size(params, sizeof(params) / sizeof(*params))