blob: 274ca4efdfbea8158a57ffd589014a2ca1cf67f3 [file] [log] [blame]
/* 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 */