msgbuf: Add insert and span APIs
pldm_msgbuf_insert() is generic APIs to insert data to a pointer.
It automatically calls the correct insertor API for the type of the
packing data.
pldm_msgbuf_span_required() spans the input number of bytes from
buffer to the input double pointer.
pldm_msgbuf_span_remaining() extracts the remaining number of bytes
from buffer to the input double pointer.
Signed-off-by: Thu Nguyen <thu@os.amperecomputing.com>
Change-Id: Ide7dbf735f69a8288e6f39a0b7b5c33aad38a98e
diff --git a/src/msgbuf.h b/src/msgbuf.h
index 662ba46..f5d4a54 100644
--- a/src/msgbuf.h
+++ b/src/msgbuf.h
@@ -15,8 +15,18 @@
#include <string.h>
#include <sys/types.h>
+/*
+ * Fix up C11's _Static_assert() vs C++'s static_assert().
+ *
+ * Can we please have nice things for once.
+ */
+#ifdef __cplusplus
+// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
+#define _Static_assert(...) static_assert(__VA_ARGS__)
+#endif
+
struct pldm_msgbuf {
- const uint8_t *cursor;
+ uint8_t *cursor;
ssize_t remaining;
};
@@ -366,6 +376,213 @@
_Generic((*(dst)), uint8_t \
: pldm_msgbuf_extract_array_uint8)(ctx, dst, count)
+static inline int pldm_msgbuf_insert_uint32(struct pldm_msgbuf *ctx,
+ const uint32_t src)
+{
+ uint32_t val = htole32(src);
+
+ if (!ctx || !ctx->cursor) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ ctx->remaining -= sizeof(src);
+ assert(ctx->remaining >= 0);
+ if (ctx->remaining < 0) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ memcpy(ctx->cursor, &val, sizeof(val));
+ ctx->cursor += sizeof(src);
+
+ return PLDM_SUCCESS;
+}
+
+static inline int pldm_msgbuf_insert_uint16(struct pldm_msgbuf *ctx,
+ const uint16_t src)
+{
+ uint16_t val = htole16(src);
+
+ if (!ctx || !ctx->cursor) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ ctx->remaining -= sizeof(src);
+ assert(ctx->remaining >= 0);
+ if (ctx->remaining < 0) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ memcpy(ctx->cursor, &val, sizeof(val));
+ ctx->cursor += sizeof(src);
+
+ return PLDM_SUCCESS;
+}
+
+static inline int pldm_msgbuf_insert_uint8(struct pldm_msgbuf *ctx,
+ const uint8_t src)
+{
+ if (!ctx || !ctx->cursor) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ ctx->remaining -= sizeof(src);
+ assert(ctx->remaining >= 0);
+ if (ctx->remaining < 0) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ memcpy(ctx->cursor, &src, sizeof(src));
+ ctx->cursor += sizeof(src);
+
+ return PLDM_SUCCESS;
+}
+
+static inline int pldm_msgbuf_insert_int32(struct pldm_msgbuf *ctx,
+ const int32_t src)
+{
+ int32_t val = htole32(src);
+
+ if (!ctx || !ctx->cursor) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ ctx->remaining -= sizeof(src);
+ assert(ctx->remaining >= 0);
+ if (ctx->remaining < 0) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ memcpy(ctx->cursor, &val, sizeof(val));
+ ctx->cursor += sizeof(src);
+
+ return PLDM_SUCCESS;
+}
+
+static inline int pldm_msgbuf_insert_int16(struct pldm_msgbuf *ctx,
+ const int16_t src)
+{
+ int16_t val = htole16(src);
+
+ if (!ctx || !ctx->cursor) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ ctx->remaining -= sizeof(src);
+ assert(ctx->remaining >= 0);
+ if (ctx->remaining < 0) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ memcpy(ctx->cursor, &val, sizeof(val));
+ ctx->cursor += sizeof(src);
+
+ return PLDM_SUCCESS;
+}
+
+static inline int pldm_msgbuf_insert_int8(struct pldm_msgbuf *ctx,
+ const int8_t src)
+{
+ if (!ctx || !ctx->cursor) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ ctx->remaining -= sizeof(src);
+ assert(ctx->remaining >= 0);
+ if (ctx->remaining < 0) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ memcpy(ctx->cursor, &src, sizeof(src));
+ ctx->cursor += sizeof(src);
+
+ return PLDM_SUCCESS;
+}
+
+#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)(dst, src)
+
+static inline int pldm_msgbuf_insert_array_uint8(struct pldm_msgbuf *ctx,
+ const uint8_t *src,
+ size_t count)
+{
+ size_t len;
+ if (!ctx || !ctx->cursor || !src) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if (!count) {
+ return PLDM_SUCCESS;
+ }
+
+ len = sizeof(*src) * count;
+ if (len > SSIZE_MAX) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ ctx->remaining -= (ssize_t)len;
+ assert(ctx->remaining >= 0);
+ if (ctx->remaining < 0) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ memcpy(ctx->cursor, src, len);
+ ctx->cursor += len;
+
+ return PLDM_SUCCESS;
+}
+
+#define pldm_msgbuf_insert_array(dst, src, count) \
+ _Generic((*(src)), uint8_t \
+ : pldm_msgbuf_insert_array_uint8)(dst, src, count)
+
+static inline int pldm_msgbuf_span_required(struct pldm_msgbuf *ctx,
+ size_t required, void **cursor)
+{
+ if (!ctx || !ctx->cursor || !cursor || *cursor) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if (required > SSIZE_MAX) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ ctx->remaining -= (ssize_t)required;
+ assert(ctx->remaining >= 0);
+ if (ctx->remaining < 0) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ *cursor = ctx->cursor;
+ ctx->cursor += required;
+
+ return PLDM_SUCCESS;
+}
+
+static inline int pldm_msgbuf_span_remaining(struct pldm_msgbuf *ctx,
+ void **cursor, size_t *len)
+{
+ if (!ctx || !ctx->cursor || !cursor || *cursor || !len) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ assert(ctx->remaining >= 0);
+ if (ctx->remaining < 0) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ *cursor = ctx->cursor;
+ ctx->cursor += ctx->remaining;
+ *len = ctx->remaining;
+ ctx->remaining = 0;
+
+ return PLDM_SUCCESS;
+}
#ifdef __cplusplus
}
#endif