diff --git a/src/brei-shared.c b/src/brei-shared.c index faa378d..2b7e5af 100644 --- a/src/brei-shared.c +++ b/src/brei-shared.c @@ -275,25 +275,25 @@ brei_marshal(struct brei_context *brei, struct iobuf *buf, const char *signature switch (*s) { case 'i': i = va_arg(args, int32_t); - iobuf_append(buf, (const char*)(&i), 4); + iobuf_append_u32(buf, i); break; case 'u': u = va_arg(args, uint32_t); - iobuf_append(buf, (const char*)(&u), 4); + iobuf_append_u32(buf, u); break; case 'x': x = va_arg(args, int64_t); - iobuf_append(buf, (const char*)(&x), 8); + iobuf_append_u64(buf, x); break; case 'o': case 'n': case 't': t = va_arg(args, uint64_t); - iobuf_append(buf, (const char*)(&t), 8); + iobuf_append_u64(buf, t); break; case 'f': f = va_arg(args, double); - iobuf_append(buf, (const char*)(&f), 4); + iobuf_append_f32(buf, f); break; case 'h': fd = va_arg(args, int); @@ -304,8 +304,8 @@ brei_marshal(struct brei_context *brei, struct iobuf *buf, const char *signature const char *str = va_arg(args, const char*); /* FIXME: nullable strings */ - size_t slen = str ? strlen(str) + 1 : 0; - iobuf_append(buf, (const char*)&slen, 4); + uint32_t slen = str ? strlen(str) + 1 : 0; + iobuf_append_u32(buf, slen); if (slen > 0) { iobuf_append(buf, str, slen); if (slen % 4) diff --git a/src/util-io.c b/src/util-io.c index 0fd7ae7..d1de09c 100644 --- a/src/util-io.c +++ b/src/util-io.c @@ -223,6 +223,14 @@ iobuf_resize(struct iobuf *buf, size_t to_size) buf->sz = to_size; } +static inline void +iobuf_extend(struct iobuf *buf, size_t extra) +{ + size_t newsize = buf->len + extra; + if (newsize > buf->sz) + iobuf_resize(buf, newsize); +} + /** * Remove the data bytes from the buffer. The caller must free() the data. * The buffer state is the same as iobuf_new() after this call. @@ -249,15 +257,41 @@ iobuf_append(struct iobuf *buf, const char *data, size_t len) if (len == 0) return; - if (buf->len + len > buf->sz) { - size_t newsize = buf->len + len; - iobuf_resize(buf, newsize); - } - + iobuf_extend(buf, len); memcpy(buf->data + buf->len, data, len); buf->len += len; } +void +iobuf_append_u32(struct iobuf *buf, uint32_t data) +{ + size_t len = 4; + + iobuf_extend(buf, len); + memcpy(buf->data + buf->len, &data, len); + buf->len += len; +} + +void +iobuf_append_u64(struct iobuf *buf, uint64_t data) +{ + size_t len = 8; + + iobuf_extend(buf, len); + memcpy(buf->data + buf->len, &data, len); + buf->len += len; +} + +void +iobuf_append_f32(struct iobuf *buf, float data) +{ + size_t len = 4; + + iobuf_extend(buf, len); + memcpy(buf->data + buf->len, &data, len); + buf->len += len; +} + /** * Prepend the given data to the buffer. */ @@ -510,6 +544,47 @@ MUNIT_TEST(test_iobuf_append_prepend) return MUNIT_OK; } +MUNIT_TEST(test_iobuf_append_values) +{ + _cleanup_iobuf_ struct iobuf *buf = iobuf_new(10); + + iobuf_append_u32(buf, -1); + size_t expected_size = 4; + + munit_assert_size(buf->len, ==, expected_size); + munit_assert_size(iobuf_len(buf), ==, expected_size); + munit_assert_size(buf->sz, ==, 10); + + const char *bufdata = iobuf_data(buf); + munit_assert_int(bufdata[0], ==, 0xff); + munit_assert_int(bufdata[1], ==, 0xff); + munit_assert_int(bufdata[2], ==, 0xff); + munit_assert_int(bufdata[3], ==, 0xff); + + free(iobuf_take_data(buf)); /* drops and replaces current buffer */ + + iobuf_append_u64(buf, 0xabababababababab); + expected_size = 8; + + munit_assert_size(buf->len, ==, expected_size); + munit_assert_size(iobuf_len(buf), ==, expected_size); + munit_assert_size(buf->sz, ==, 10); + + bufdata = iobuf_data(buf); + munit_assert_int((unsigned char)bufdata[0], ==, 0xab); + munit_assert_int((unsigned char)bufdata[1], ==, 0xab); + munit_assert_int((unsigned char)bufdata[2], ==, 0xab); + munit_assert_int((unsigned char)bufdata[3], ==, 0xab); + munit_assert_int((unsigned char)bufdata[4], ==, 0xab); + munit_assert_int((unsigned char)bufdata[5], ==, 0xab); + munit_assert_int((unsigned char)bufdata[6], ==, 0xab); + munit_assert_int((unsigned char)bufdata[7], ==, 0xab); + + free(iobuf_take_data(buf)); + + return MUNIT_OK; +} + MUNIT_TEST(test_iobuf_prepend_empty_buffer) { /* Test prepending data */ diff --git a/src/util-io.h b/src/util-io.h index c91f00f..15cd97d 100644 --- a/src/util-io.h +++ b/src/util-io.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -304,6 +305,27 @@ iobuf_pop(struct iobuf *buf, size_t nbytes); void iobuf_append(struct iobuf *buf, const char *data, size_t len); +/** + * Append one 32-bit value to the buffer. If the data exceeds the current buffer + * size it is resized automatically. + */ +void +iobuf_append_u32(struct iobuf *buf, uint32_t data); + +/** + * Append one 64-bit value to the buffer. If the data exceeds the current buffer + * size it is resized automatically. + */ +void +iobuf_append_u64(struct iobuf *buf, uint64_t data); + +/** + * Append one 32-bit float to the buffer. If the data exceeds the current buffer + * size it is resized automatically. + */ +void +iobuf_append_f32(struct iobuf *buf, float data); + /** * Prepend len bytes to the buffer. If the data exceeds the current buffer * size it is resized automatically.