interfaces/inc/c_pal/malloc_multi_flex.h (92 lines of code) (raw):
// Copyright (c) Microsoft. All rights reserved.
#ifndef MALLOC_MULTI_FLEX_STRUCT_H
#define MALLOC_MULTI_FLEX_STRUCT_H
#ifdef __cplusplus
#include <cstddef>
#include <cstdint>
#include <cstdalign>
#else
#include <stddef.h>
#include <stdint.h>
#include <stdalign.h>
#endif
#include "macro_utils/macro_utils.h"
#include "c_pal/gballoc_hl.h"
#include "c_pal/gballoc_hl_redirect.h"
#include "c_logging/logger.h"
#include "umock_c/umock_c_prod.h"
#ifdef __cplusplus
extern "C" {
#endif
//overflow check
#define MALLOC_MULTI_FLEX_STRUCT_ARG_OVERFLOW_CHECK(arg1, arg2) \
if ((sizeof(arg1) != 0 && SIZE_MAX / sizeof(arg1) < MU_C2(arg2, _count)) || (SIZE_MAX - size_required < MU_C2(arg2, _count) * sizeof(arg1)) || (SIZE_MAX - (size_required + MU_C2(arg2, _count) * sizeof(arg1)) < alignof(arg1)))\
{\
LogError("Size required to allocate memory for struct exceeds %" PRIu64 "", SIZE_MAX);\
return NULL;\
}\
size_required += MU_C2(arg2, _count) * sizeof(arg1) + alignof(arg1) - 1;
#define MALLOC_MULTI_FLEX_STRUCT_ARG_OVERFLOW_CHECK_ARRAY_FIELDS(...) \
MU_FOR_EACH_2(MALLOC_MULTI_FLEX_STRUCT_ARG_OVERFLOW_CHECK, __VA_ARGS__)
#define MALLOC_MULTI_FLEX_STRUCT_ARGS_OVERFLOW_CHECK(array_fields) \
MU_C2A(MALLOC_MULTI_FLEX_STRUCT_ARG_OVERFLOW_CHECK_, array_fields)
#define MALLOC_MULTI_FLEX_STRUCT_DEFINE_ARG_LIST_VALUE(arg1, arg2) \
, size_t MU_C2(arg2, _count)
#define MALLOC_MULTI_FLEX_STRUCT_DEFINE_ARG_LIST_VALUE_ARRAY_FIELDS(...) \
MU_FOR_EACH_2(MALLOC_MULTI_FLEX_STRUCT_DEFINE_ARG_LIST_VALUE, __VA_ARGS__)
#define MALLOC_MULTI_FLEX_STRUCT_DEFINE_ARG_LIST_VALUES(array_fields) \
MU_C2A(MALLOC_MULTI_FLEX_STRUCT_DEFINE_ARG_LIST_VALUE_, array_fields)
#define MALLOC_MULTI_FLEX_STRUCT_DECLARE_ARG_LIST_VALUE(arg1, arg2) \
, size_t, MU_C2(arg2, _count)
#define MALLOC_MULTI_FLEX_STRUCT_DECLARE_ARG_LIST_VALUE_ARRAY_FIELDS(...) \
MU_FOR_EACH_2(MALLOC_MULTI_FLEX_STRUCT_DECLARE_ARG_LIST_VALUE, __VA_ARGS__)
#define MALLOC_MULTI_FLEX_STRUCT_DECLARE_ARG_LIST_VALUES(array_fields) \
MU_C2A(MALLOC_MULTI_FLEX_STRUCT_DECLARE_ARG_LIST_VALUE_, array_fields)
#define MALLOC_MULTI_FLEX_STRUCT_ASSIGN_INTERNAL_STRUCT_PTR(arg1, arg2) \
parent_struct_pointer->arg2 = (arg1*)(pointer_iterator + (uintptr_t)(alignof(arg1) - ((uintptr_t)pointer_iterator % alignof(arg1))) % alignof(arg1));\
pointer_iterator = (uintptr_t)pointer_iterator + MU_C2(arg2, _count) * sizeof(arg1);
#define MALLOC_MULTI_FLEX_STRUCT_ASSIGN_INTERNAL_STRUCT_PTR_ARRAY_FIELDS(...) \
MU_FOR_EACH_2(MALLOC_MULTI_FLEX_STRUCT_ASSIGN_INTERNAL_STRUCT_PTR, __VA_ARGS__)
#define MALLOC_MULTI_FLEX_STRUCT_ASSIGN_INTERNAL_STRUCT_PTRS(array_fields) \
MU_C2A(MALLOC_MULTI_FLEX_STRUCT_ASSIGN_INTERNAL_STRUCT_PTR_, array_fields)
/* Codes_SRS_MALLOC_MULTI_FLEX_STRUCT_24_005: [ MALLOC_MULTI_FLEX_STRUCT shall expand type to the name of the malloc function in the format of: MALLOC_MULTI_FLEX_STRUCT_type. ]*/
#define MALLOC_MULTI_FLEX_STRUCT(type) \
MU_C2(malloc_multi_flex_, type) \
#define MALLOC_MULTI_FLEX_STRUCT_DEFINE_FIELD_MEMBER(arg1, arg2) \
arg1 arg2;
#define MALLOC_MULTI_FLEX_STRUCT_DEFINE_MEMBERS_FIELDS(...) \
MU_FOR_EACH_2(MALLOC_MULTI_FLEX_STRUCT_DEFINE_FIELD_MEMBER, __VA_ARGS__)
#define MALLOC_MULTI_FLEX_STRUCT_DEFINE_ARRAY_FIELD_MEMBER(arg1, arg2) \
arg1* arg2;
#define MALLOC_MULTI_FLEX_STRUCT_DEFINE_MEMBERS_ARRAY_FIELDS(...) \
MU_FOR_EACH_2(MALLOC_MULTI_FLEX_STRUCT_DEFINE_ARRAY_FIELD_MEMBER, __VA_ARGS__)
#define GENERATE_MULTI_MALLOC_STRUCT(fields) \
MU_C2A(MALLOC_MULTI_FLEX_STRUCT_DEFINE_MEMBERS_, fields) \
#define DECLARE_MALLOC_MULTI_FLEX_STRUCT(type, fields, array_fields)\
typedef struct MU_C2(type, _TAG) \
{ \
GENERATE_MULTI_MALLOC_STRUCT(fields)\
GENERATE_MULTI_MALLOC_STRUCT(array_fields)\
} type; \
MOCKABLE_FUNCTION(, void*, MALLOC_MULTI_FLEX_STRUCT(type), size_t, parent_struct_size MALLOC_MULTI_FLEX_STRUCT_DECLARE_ARG_LIST_VALUES(array_fields)); \
#define DEFINE_MALLOC_MULTI_FLEX_STRUCT(type, fields, array_fields)\
void* MALLOC_MULTI_FLEX_STRUCT(type)(size_t parent_struct_size MALLOC_MULTI_FLEX_STRUCT_DEFINE_ARG_LIST_VALUES(array_fields)) \
{\
size_t size_required = parent_struct_size;\
/* Codes_SRS_MALLOC_MULTI_FLEX_STRUCT_24_001: [ If the total amount of memory required to allocate the type along with its members exceeds SIZE_MAX then DEFINE_MALLOC_MULTI_FLEX_STRUCT shall fail and return NULL. ]*/ \
MALLOC_MULTI_FLEX_STRUCT_ARGS_OVERFLOW_CHECK(array_fields)\
/* Codes_SRS_MALLOC_MULTI_FLEX_STRUCT_24_002: [ DEFINE_MALLOC_MULTI_FLEX_STRUCT shall call malloc to allocate memory for the struct and its members. ]*/ \
type* parent_struct_pointer = malloc(size_required);\
if (parent_struct_pointer == NULL)\
{\
/* Codes_SRS_MALLOC_MULTI_FLEX_STRUCT_24_006: [ If malloc fails, DEFINE_MALLOC_MULTI_FLEX_STRUCT shall fail and return NULL. ]*/ \
LogError("malloc(size_required = %zu) failed", size_required);\
return NULL;\
}\
uintptr_t pointer_iterator = (uintptr_t)parent_struct_pointer + parent_struct_size; \
/* Codes_SRS_MALLOC_MULTI_FLEX_STRUCT_24_003: [ DEFINE_MALLOC_MULTI_FLEX_STRUCT shall assign address pointers to all the member arrays. ]*/ \
MALLOC_MULTI_FLEX_STRUCT_ASSIGN_INTERNAL_STRUCT_PTRS(array_fields)\
/* Codes_SRS_MALLOC_MULTI_FLEX_STRUCT_24_004: [ DEFINE_MALLOC_MULTI_FLEX_STRUCT shall succeed and return the address returned by malloc. ]*/ \
return parent_struct_pointer;\
}\
#ifdef __cplusplus
}
#endif
#endif // MALLOC_MULTI_FLEX_STRUCT_H