| /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ | 
 | #ifndef PLDM_MSGBUF_H | 
 | #define PLDM_MSGBUF_H | 
 |  | 
 | #include "msgbuf/core.h" | 
 |  | 
 | #define PLDM__MSGBUF_DEFINE_P(name, mode)                                      \ | 
 | 	struct pldm_msgbuf_##mode _##name LIBPLDM_CC_CLEANUP(                  \ | 
 | 		pldm__msgbuf_##mode##_cleanup) = { NULL, INTMAX_MIN };         \ | 
 | 	struct pldm_msgbuf_##mode *(name) = &(_##name) | 
 |  | 
 | #define PLDM_MSGBUF_RO_DEFINE_P(name) PLDM__MSGBUF_DEFINE_P(name, ro) | 
 | #define PLDM_MSGBUF_RW_DEFINE_P(name) PLDM__MSGBUF_DEFINE_P(name, rw) | 
 |  | 
 | /* | 
 |  * Use the C11 `_Generic` keyword to keep pldm_msgbuf related function consistent | 
 |  * and to produce compile-time errors when the wrong pldm_msgbuf type is passed. | 
 |  * | 
 |  * Previously we cast away `const` in `pldm_msgbuf_init_error()`, which was a hack. | 
 |  * Instead, introduce: | 
 |  *   - pldm_msgbuf_ro: read-only buffer with a `const` cursor | 
 |  *   - pldm_msgbuf_rw: read-write buffer with a non-const cursor | 
 |  * | 
 |  * `pldm_msgbuf_ro` is used by decode APIs to extract payloads into PLDM | 
 |  * structures. `pldm_msgbuf_rw` is used by encode APIs to insert payloads from | 
 |  * PLDM structures. | 
 |  */ | 
 |  | 
 | #define pldm_msgbuf_init_errno(ctx, minsize, buf, len)                         \ | 
 | 	_Generic((ctx),                                                        \ | 
 | 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_init_errno,            \ | 
 | 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_init_errno)(           \ | 
 | 		ctx, minsize, buf, len) | 
 |  | 
 | #define pldm_msgbuf_discard(ctx, error)                                        \ | 
 | 	_Generic((ctx),                                                        \ | 
 | 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_discard,               \ | 
 | 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_discard)(ctx, error) | 
 |  | 
 | #define pldm_msgbuf_complete(ctx)                                              \ | 
 | 	_Generic((ctx),                                                        \ | 
 | 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_complete,              \ | 
 | 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_complete)(ctx) | 
 |  | 
 | #define pldm_msgbuf_complete_consumed(ctx)                                     \ | 
 | 	_Generic((ctx),                                                        \ | 
 | 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_complete_consumed,     \ | 
 | 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_complete_consumed)(    \ | 
 | 		ctx) | 
 |  | 
 | #define pldm_msgbuf_validate(ctx)                                              \ | 
 | 	_Generic((ctx),                                                        \ | 
 | 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_validate,              \ | 
 | 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_validate)(ctx) | 
 |  | 
 | #define pldm_msgbuf_consumed(ctx)                                              \ | 
 | 	_Generic((ctx),                                                        \ | 
 | 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_consumed,              \ | 
 | 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_consumed)(ctx) | 
 |  | 
 | #define pldm__msgbuf_invalidate(ctx)                                           \ | 
 | 	_Generic((ctx),                                                        \ | 
 | 		struct pldm_msgbuf_rw *: pldm__msgbuf_rw_invalidate,           \ | 
 | 		struct pldm_msgbuf_ro *: pldm__msgbuf_ro_invalidate)(ctx) | 
 |  | 
 | #define pldm_msgbuf_span_required(ctx, required, cursor)                       \ | 
 | 	_Generic((ctx),                                                        \ | 
 | 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_span_required,         \ | 
 | 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_span_required)(        \ | 
 | 		ctx, required, cursor) | 
 |  | 
 | #define pldm_msgbuf_span_until(ctx, trailer, cursor, length)                   \ | 
 | 	_Generic((ctx),                                                        \ | 
 | 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_span_until,            \ | 
 | 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_span_until)(           \ | 
 | 		ctx, trailer, cursor, length) | 
 |  | 
 | #define pldm_msgbuf_span_string_utf16(ctx, cursor, len)                        \ | 
 | 	_Generic((ctx),                                                        \ | 
 | 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_span_string_utf16,     \ | 
 | 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_span_string_utf16)(    \ | 
 | 		ctx, cursor, len) | 
 |  | 
 | #define pldm_msgbuf_span_remaining(ctx, cursor, len)                           \ | 
 | 	_Generic((ctx),                                                        \ | 
 | 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_span_remaining,        \ | 
 | 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_span_remaining)(       \ | 
 | 		ctx, cursor, len) | 
 |  | 
 | #define pldm_msgbuf_span_string_ascii(ctx, cursor, len)                        \ | 
 | 	_Generic((ctx),                                                        \ | 
 | 		struct pldm_msgbuf_rw *: pldm_msgbuf_rw_span_string_ascii,     \ | 
 | 		struct pldm_msgbuf_ro *: pldm_msgbuf_ro_span_string_ascii)(    \ | 
 | 		ctx, cursor, len) | 
 |  | 
 | #define pldm_msgbuf_extract_typecheck(ty, fn, dst, ...)                        \ | 
 | 	(pldm_require_obj_type(dst, ty), fn(__VA_ARGS__)) | 
 |  | 
 | #define pldm_msgbuf_extract_uint8(ctx, dst)                                    \ | 
 | 	pldm_msgbuf_extract_typecheck(uint8_t, pldm__msgbuf_extract_uint8,     \ | 
 | 				      dst, ctx, (void *)&(dst)) | 
 |  | 
 | #define pldm_msgbuf_extract_int8(ctx, dst)                                     \ | 
 | 	pldm_msgbuf_extract_typecheck(int8_t, pldm__msgbuf_extract_int8, dst,  \ | 
 | 				      ctx, (void *)&(dst)) | 
 |  | 
 | #define pldm_msgbuf_extract_uint16(ctx, dst)                                   \ | 
 | 	pldm_msgbuf_extract_typecheck(uint16_t, pldm__msgbuf_extract_uint16,   \ | 
 | 				      dst, ctx, (void *)&(dst)) | 
 |  | 
 | #define pldm_msgbuf_extract_int16(ctx, dst)                                    \ | 
 | 	pldm_msgbuf_extract_typecheck(int16_t, pldm__msgbuf_extract_int16,     \ | 
 | 				      dst, ctx, (void *)&(dst)) | 
 |  | 
 | #define pldm_msgbuf_extract_uint32(ctx, dst)                                   \ | 
 | 	pldm_msgbuf_extract_typecheck(uint32_t, pldm__msgbuf_extract_uint32,   \ | 
 | 				      dst, ctx, (void *)&(dst)) | 
 |  | 
 | #define pldm_msgbuf_extract_int32(ctx, dst)                                    \ | 
 | 	pldm_msgbuf_extract_typecheck(int32_t, pldm__msgbuf_extract_int32,     \ | 
 | 				      dst, ctx, (void *)&(dst)) | 
 |  | 
 | #define pldm_msgbuf_extract_real32(ctx, dst)                                   \ | 
 | 	pldm_msgbuf_extract_typecheck(real32_t, pldm__msgbuf_extract_real32,   \ | 
 | 				      dst, ctx, (void *)&(dst)) | 
 |  | 
 | /** | 
 |  * Extract the field at the msgbuf cursor into the lvalue named by dst. | 
 |  * | 
 |  * @param ctx The msgbuf context object | 
 |  * @param dst The lvalue into which the field at the msgbuf cursor should be | 
 |  *            extracted | 
 |  * | 
 |  * @return PLDM_SUCCESS on success, otherwise another value on error | 
 |  */ | 
 | #define pldm_msgbuf_extract(ctx, dst)                                          \ | 
 | 	_Generic((dst),                                                        \ | 
 | 		uint8_t: pldm__msgbuf_extract_uint8,                           \ | 
 | 		int8_t: pldm__msgbuf_extract_int8,                             \ | 
 | 		uint16_t: pldm__msgbuf_extract_uint16,                         \ | 
 | 		int16_t: pldm__msgbuf_extract_int16,                           \ | 
 | 		uint32_t: pldm__msgbuf_extract_uint32,                         \ | 
 | 		int32_t: pldm__msgbuf_extract_int32,                           \ | 
 | 		real32_t: pldm__msgbuf_extract_real32)(ctx, (void *)&(dst)) | 
 |  | 
 | /** | 
 |  * Extract the field at the msgbuf cursor into the object pointed-to by dst. | 
 |  * | 
 |  * @param ctx The msgbuf context object | 
 |  * @param dst The pointer to the object into which the field at the msgbuf | 
 |  *            cursor should be extracted | 
 |  * | 
 |  * @return PLDM_SUCCESS on success, otherwise another value on error | 
 |  */ | 
 | #define pldm_msgbuf_extract_p(ctx, dst)                                        \ | 
 | 	_Generic((dst),                                                        \ | 
 | 		uint8_t *: pldm__msgbuf_extract_uint8,                         \ | 
 | 		int8_t *: pldm__msgbuf_extract_int8,                           \ | 
 | 		uint16_t *: pldm__msgbuf_extract_uint16,                       \ | 
 | 		int16_t *: pldm__msgbuf_extract_int16,                         \ | 
 | 		uint32_t *: pldm__msgbuf_extract_uint32,                       \ | 
 | 		int32_t *: pldm__msgbuf_extract_int32,                         \ | 
 | 		real32_t *: pldm__msgbuf_extract_real32)(ctx, dst) | 
 |  | 
 | #define pldm_msgbuf_insert(dst, src)                                           \ | 
 | 	_Generic((src),                                                        \ | 
 | 		uint8_t: pldm_msgbuf_insert_uint8,                             \ | 
 | 		int8_t: pldm_msgbuf_insert_int8,                               \ | 
 | 		uint16_t: pldm_msgbuf_insert_uint16,                           \ | 
 | 		int16_t: pldm_msgbuf_insert_int16,                             \ | 
 | 		uint32_t: pldm_msgbuf_insert_uint32,                           \ | 
 | 		int32_t: pldm_msgbuf_insert_int32,                             \ | 
 | 		uint64_t: pldm_msgbuf_insert_uint64)(dst, src) | 
 |  | 
 | /** | 
 |  * Insert an array of data into the msgbuf instance | 
 |  * | 
 |  * @param ctx - The msgbuf instance into which the array of data should be | 
 |  *              inserted | 
 |  * @param count - The number of array elements to insert | 
 |  * @param src - The array object from which elements should be inserted into | 
 |                 @p ctx | 
 |  * @param src_count - The maximum number of elements to insert from @p src | 
 |  * | 
 |  * Note that both @p count and @p src_count can only be counted by `sizeof` for | 
 |  * arrays where `sizeof(*dst) == 1` holds. Specifically, they count the number | 
 |  * of array elements and _not_ the object size of the array. | 
 |  */ | 
 | #define pldm_msgbuf_insert_array(dst, count, src, src_count)                   \ | 
 | 	_Generic((*(src)),                                                     \ | 
 | 		uint8_t: pldm_msgbuf_insert_array_uint8,                       \ | 
 | 		char: pldm_msgbuf_insert_array_char)(dst, count, src,          \ | 
 | 						     src_count) | 
 |  | 
 | #endif /* BUF_H */ |