msgbuf: Add pldm_msgbuf_span_until()

pldm_msgbuf_span_until() extracts the indirectly-specified range from
the current cursor position until the offset where only `trailer` bytes
remain in the buffer.

Change-Id: Icb70a3af54f21ba1afd311699cb860bf24bb155e
Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
diff --git a/src/msgbuf.h b/src/msgbuf.h
index a0e1204..78ec89a 100644
--- a/src/msgbuf.h
+++ b/src/msgbuf.h
@@ -1141,6 +1141,42 @@
 	return 0;
 }
 
+LIBPLDM_CC_NONNULL_ARGS(1)
+LIBPLDM_CC_ALWAYS_INLINE
+int pldm_msgbuf_span_until(struct pldm_msgbuf *ctx, size_t trailer,
+			   void **cursor, size_t *length)
+{
+#if INTMAX_MAX < SIZE_MAX
+	if (trailer > INTMAX_MAX) {
+		return pldm__msgbuf_invalidate(ctx);
+	}
+#endif
+
+	if (ctx->remaining >= (intmax_t)trailer) {
+		ptrdiff_t delta;
+
+		assert(ctx->cursor);
+
+		delta = ctx->remaining - (intmax_t)trailer;
+		if (cursor) {
+			*cursor = ctx->cursor;
+		}
+		ctx->cursor += delta;
+		if (length) {
+			*length = delta;
+		}
+		ctx->remaining = (intmax_t)trailer;
+		return 0;
+	}
+
+	if (ctx->remaining > INTMAX_MIN + (intmax_t)trailer) {
+		ctx->remaining = INTMAX_MIN + (intmax_t)trailer;
+		return -EOVERFLOW;
+	}
+
+	return pldm__msgbuf_invalidate(ctx);
+}
+
 LIBPLDM_CC_NONNULL
 LIBPLDM_CC_ALWAYS_INLINE int
 pldm_msgbuf_peek_remaining(struct pldm_msgbuf *ctx, void **cursor, size_t *len)