| /* 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 */ |