First iteration of mbuf, message buffer api
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
#ifndef UC_MBUF_H_
|
||||
#define UC_MBUF_H_
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define UC_INLINE inline __attribute__((always_inline))
|
||||
#else
|
||||
# define UC_INLINE inline
|
||||
#endif
|
||||
|
||||
enum UC_MBUF_FLAGS {
|
||||
UC_MBUF_FL_MALLOC = 0x0001, //MBuf and MBuf->bufstart are seperatly malloc'd
|
||||
UC_MBUF_FL_MALLOC_BUF = 0x0001, //MBuf is not malloc'd. MBuf->bufstart is malloc'd
|
||||
UC_MBUF_FL_MALLOC_INLINE = 0x0002, //MBuf is one big malloc. Can't be resized
|
||||
UC_MBUF_FL_STATIC = 0x0004, //MBuf and MBuf->bustart is user controlled. Can't be resized
|
||||
};
|
||||
|
||||
struct MBuf {
|
||||
struct MBuf *next;
|
||||
uint8_t *p1;
|
||||
uint8_t *p2;
|
||||
uint8_t *p3;
|
||||
uint8_t *p4;
|
||||
void *cookie;
|
||||
uint32_t flags;
|
||||
uint32_t allocated;
|
||||
uint8_t *bufstart;
|
||||
uint8_t *head;
|
||||
uint8_t *tail;
|
||||
uint8_t inline_data[0];
|
||||
};
|
||||
|
||||
/* Conventions:
|
||||
* push - prepend data to the buffer (in the head room part)
|
||||
* pull - remove data from the beginning of the message.
|
||||
* put - Add data to the buffer.
|
||||
*/
|
||||
struct MBuf *uc_mbuf_new_hr(uint32_t len, uint32_t headroom);
|
||||
#define uc_mbuf_new(len) uc_mbuf_new_hr((len), 0)
|
||||
|
||||
struct MBuf *uc_mbuf_new_inline_hr(uint32_t len, uint32_t headroom);
|
||||
#define uc_mbuf_new_inline(len) uc_mbuf_new_inline_hr((len), 0)
|
||||
|
||||
void uc_mbuf_free(struct MBuf *mbuf);
|
||||
struct MBuf *uc_mbuf_copy(struct MBuf *mbuf);
|
||||
|
||||
void uc_mbuf_init(struct MBuf *mbuf, uint8_t *buf, uint32_t len, uint32_t headroom, uint32_t flags);
|
||||
void uc_mbuf_zero(struct MBuf *mbuf);
|
||||
void uc_mbuf_reset(struct MBuf *mbuf);
|
||||
|
||||
static UC_INLINE uint32_t uc_mbuf_len(struct MBuf *mbuf)
|
||||
{
|
||||
return (uint32_t)(mbuf->tail - mbuf->head);
|
||||
}
|
||||
|
||||
static UC_INLINE uint32_t uc_mbuf_tailroom(struct MBuf *mbuf)
|
||||
{
|
||||
return mbuf->allocated - (uint32_t)(mbuf->tail - mbuf->bufstart);
|
||||
}
|
||||
|
||||
static inline uint32_t uc_mbuf_headroom(struct MBuf *mbuf)
|
||||
{
|
||||
return (uint32_t)(mbuf->head - mbuf->bufstart);
|
||||
}
|
||||
|
||||
uint8_t *uc_mbuf_put(struct MBuf *mbuf, uint32_t size);
|
||||
|
||||
uint8_t *uc_mbuf_push(struct MBuf *mbuf, uint32_t size);
|
||||
|
||||
uint8_t *uc_mbuf_pull(struct MBuf *mbuf, uint32_t size);
|
||||
|
||||
struct MBuf *uc_uc_mbuf_new_hr(uint32_t len, uint32_t headroom);
|
||||
struct MBuf *uc_uc_mbuf_new_inline_hr(uint32_t len, uint32_t headroom);
|
||||
|
||||
#undef UC_INLINE
|
||||
|
||||
#endif
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "ucore/mbuf.h"
|
||||
|
||||
uint8_t *uc_mbuf_put(struct MBuf *mbuf, uint32_t size)
|
||||
{
|
||||
uint8_t *data = mbuf->tail;
|
||||
if (uc_mbuf_tailroom(mbuf) < size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbuf->tail += size;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
uint8_t *uc_mbuf_push(struct MBuf *mbuf, uint32_t size)
|
||||
{
|
||||
if (uc_mbuf_headroom(mbuf) < size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbuf->head -= size;
|
||||
|
||||
return mbuf->head;
|
||||
}
|
||||
|
||||
uint8_t *uc_mbuf_pull(struct MBuf *mbuf, uint32_t size)
|
||||
{
|
||||
uint8_t *data = mbuf->head;
|
||||
if (uc_mbuf_len(mbuf) < size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbuf->head += size;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
void uc_mbuf_init(struct MBuf *mbuf, uint8_t *buf, uint32_t len, uint32_t headroom, uint32_t flags)
|
||||
{
|
||||
mbuf->bufstart = buf;
|
||||
mbuf->next = NULL;
|
||||
mbuf->p1 = mbuf->p2 = mbuf->p3 = mbuf->p4 = NULL;
|
||||
mbuf->cookie = NULL;
|
||||
mbuf->flags = flags;
|
||||
mbuf->allocated = len + headroom;
|
||||
mbuf->head = mbuf->bufstart + headroom;
|
||||
mbuf->tail = mbuf->head;
|
||||
}
|
||||
|
||||
struct MBuf *uc_mbuf_new_hr(uint32_t len, uint32_t headroom)
|
||||
{
|
||||
struct MBuf *mbuf;
|
||||
uint8_t *buf;
|
||||
|
||||
mbuf = malloc(sizeof *mbuf);
|
||||
if (mbuf == NULL)
|
||||
return mbuf;
|
||||
|
||||
buf = malloc(len + headroom);
|
||||
if (buf == NULL) {
|
||||
free(mbuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uc_mbuf_init(mbuf, buf, len, headroom, UC_MBUF_FL_MALLOC);
|
||||
|
||||
return mbuf;
|
||||
}
|
||||
|
||||
struct MBuf *uc_mbuf_new_inline_hr(uint32_t len, uint32_t headroom)
|
||||
{
|
||||
struct MBuf *mbuf;
|
||||
|
||||
mbuf = malloc(sizeof *mbuf + len + headroom);
|
||||
if (mbuf == NULL)
|
||||
return mbuf;
|
||||
|
||||
uc_mbuf_init(mbuf, mbuf->inline_data, len, headroom, UC_MBUF_FL_MALLOC_INLINE);
|
||||
|
||||
return mbuf;
|
||||
}
|
||||
|
||||
void uc_mbuf_free(struct MBuf *mbuf)
|
||||
{
|
||||
if (mbuf->flags & (UC_MBUF_FL_MALLOC | UC_MBUF_FL_MALLOC_BUF))
|
||||
free(mbuf->bufstart);
|
||||
|
||||
if (mbuf->flags & (UC_MBUF_FL_MALLOC | UC_MBUF_FL_MALLOC_INLINE))
|
||||
free(mbuf);
|
||||
}
|
||||
|
||||
void uc_mbuf_zero(struct MBuf *mbuf)
|
||||
{
|
||||
memset(mbuf->bufstart, 0, mbuf->allocated);
|
||||
}
|
||||
|
||||
#undef UC_INLINE
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
#include <check.h>
|
||||
#include <string.h>
|
||||
#include <ucore/mbuf.h>
|
||||
|
||||
|
||||
START_TEST (test_mbuf_new)
|
||||
struct MBuf *mbuf;
|
||||
|
||||
mbuf = uc_mbuf_new(110);
|
||||
|
||||
fail_if(mbuf == NULL);
|
||||
fail_if(uc_mbuf_len(mbuf) != 0);
|
||||
fail_if(uc_mbuf_headroom(mbuf) != 0);
|
||||
fail_if(uc_mbuf_tailroom(mbuf) != 110);
|
||||
fail_if(mbuf->next != NULL);
|
||||
fail_if(mbuf->p1 != NULL);
|
||||
fail_if(mbuf->p2 != NULL);
|
||||
fail_if(mbuf->p3 != NULL);
|
||||
fail_if(mbuf->p4 != NULL);
|
||||
fail_if(mbuf->cookie != NULL);
|
||||
fail_if(mbuf->head != mbuf->tail);
|
||||
|
||||
uc_mbuf_free(mbuf);
|
||||
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_mbuf_new_inline)
|
||||
struct MBuf *mbuf;
|
||||
|
||||
mbuf = uc_mbuf_new_inline(110);
|
||||
|
||||
fail_if(mbuf == NULL);
|
||||
fail_if(uc_mbuf_len(mbuf) != 0);
|
||||
fail_if(uc_mbuf_headroom(mbuf) != 0);
|
||||
fail_if(uc_mbuf_tailroom(mbuf) != 110);
|
||||
fail_if(mbuf->next != NULL);
|
||||
fail_if(mbuf->p1 != NULL);
|
||||
fail_if(mbuf->p2 != NULL);
|
||||
fail_if(mbuf->p3 != NULL);
|
||||
fail_if(mbuf->p4 != NULL);
|
||||
fail_if(mbuf->cookie != NULL);
|
||||
fail_if(mbuf->head != mbuf->tail);
|
||||
|
||||
uc_mbuf_free(mbuf);
|
||||
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_mbuf_new_headroom)
|
||||
struct MBuf *mbuf;
|
||||
|
||||
mbuf = uc_mbuf_new_hr(110,20);
|
||||
|
||||
fail_if(mbuf == NULL);
|
||||
fail_if(uc_mbuf_len(mbuf) != 0);
|
||||
fail_if(uc_mbuf_headroom(mbuf) != 20);
|
||||
fail_if(uc_mbuf_tailroom(mbuf) != 110);
|
||||
fail_if(mbuf->next != NULL);
|
||||
fail_if(mbuf->p1 != NULL);
|
||||
fail_if(mbuf->p2 != NULL);
|
||||
fail_if(mbuf->p3 != NULL);
|
||||
fail_if(mbuf->p4 != NULL);
|
||||
fail_if(mbuf->cookie != NULL);
|
||||
fail_if(mbuf->head != mbuf->tail);
|
||||
|
||||
uc_mbuf_free(mbuf);
|
||||
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_mbuf_put)
|
||||
struct MBuf *mbuf;
|
||||
uint8_t *data;
|
||||
|
||||
mbuf = uc_mbuf_new_inline(111);
|
||||
fail_if(mbuf == NULL);
|
||||
|
||||
data = uc_mbuf_put(mbuf, 111);
|
||||
fail_if(data == NULL);
|
||||
fail_if(uc_mbuf_len(mbuf) != 111);
|
||||
fail_if(uc_mbuf_tailroom(mbuf) != 0);
|
||||
|
||||
memset(data, 0, 111);
|
||||
|
||||
uc_mbuf_free(mbuf);
|
||||
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_mbuf_put_fail)
|
||||
struct MBuf *mbuf;
|
||||
uint8_t *data;
|
||||
|
||||
mbuf = uc_mbuf_new_inline(10);
|
||||
fail_if(mbuf == NULL);
|
||||
|
||||
data = uc_mbuf_put(mbuf, 11);
|
||||
fail_if(data != NULL);
|
||||
|
||||
uc_mbuf_free(mbuf);
|
||||
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_mbuf_push)
|
||||
struct MBuf *mbuf;
|
||||
uint8_t *data;
|
||||
|
||||
mbuf = uc_mbuf_new_hr(10,1);
|
||||
fail_if(mbuf == NULL);
|
||||
|
||||
data = uc_mbuf_push(mbuf, 1);
|
||||
fail_if(data == NULL);
|
||||
fail_if(uc_mbuf_len(mbuf) != 1);
|
||||
fail_if(uc_mbuf_headroom(mbuf) != 0);
|
||||
|
||||
*data = 0;
|
||||
|
||||
uc_mbuf_free(mbuf);
|
||||
|
||||
END_TEST
|
||||
|
||||
|
||||
START_TEST (test_mbuf_push_fail)
|
||||
struct MBuf *mbuf;
|
||||
uint8_t *data;
|
||||
|
||||
mbuf = uc_mbuf_new_hr(1,2);
|
||||
fail_if(mbuf == NULL);
|
||||
|
||||
data = uc_mbuf_push(mbuf, 3);
|
||||
fail_if(data != NULL);
|
||||
|
||||
uc_mbuf_free(mbuf);
|
||||
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_mbuf_pull)
|
||||
struct MBuf *mbuf;
|
||||
uint8_t *data1;
|
||||
uint8_t *data2;
|
||||
|
||||
mbuf = uc_mbuf_new_inline(10);
|
||||
fail_if(mbuf == NULL);
|
||||
|
||||
data1 = uc_mbuf_put(mbuf, 10);
|
||||
fail_if(data1 == NULL);
|
||||
fail_if(uc_mbuf_tailroom(mbuf) != 0);
|
||||
fail_if(uc_mbuf_len(mbuf) != 10);
|
||||
|
||||
data2 = uc_mbuf_pull(mbuf,10);
|
||||
fail_if(data2 == NULL);
|
||||
fail_if(data1 != data2);
|
||||
fail_if(uc_mbuf_len(mbuf) != 0);
|
||||
|
||||
uc_mbuf_free(mbuf);
|
||||
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_mbuf_pull_fail)
|
||||
struct MBuf *mbuf;
|
||||
uint8_t *data1;
|
||||
uint8_t *data2;
|
||||
|
||||
mbuf = uc_mbuf_new_inline(10);
|
||||
fail_if(mbuf == NULL);
|
||||
|
||||
data1 = uc_mbuf_put(mbuf, 10);
|
||||
fail_if(data1 == NULL);
|
||||
fail_if(uc_mbuf_len(mbuf) != 10);
|
||||
|
||||
data2 = uc_mbuf_pull(mbuf,11);
|
||||
fail_if(data2 != NULL);
|
||||
fail_if(uc_mbuf_len(mbuf) != 10);
|
||||
|
||||
|
||||
uc_mbuf_free(mbuf);
|
||||
|
||||
END_TEST
|
||||
|
||||
|
||||
|
||||
Suite *mbuf_suite(void)
|
||||
{
|
||||
Suite *s = suite_create("mbuf");
|
||||
TCase *tc = tcase_create("mbuf tests");
|
||||
tcase_add_test(tc, test_mbuf_new);
|
||||
tcase_add_test(tc, test_mbuf_new_inline);
|
||||
tcase_add_test(tc, test_mbuf_new_headroom);
|
||||
tcase_add_test(tc, test_mbuf_put);
|
||||
tcase_add_test(tc, test_mbuf_put_fail);
|
||||
tcase_add_test(tc, test_mbuf_push);
|
||||
tcase_add_test(tc, test_mbuf_push_fail);
|
||||
tcase_add_test(tc, test_mbuf_pull);
|
||||
tcase_add_test(tc, test_mbuf_pull_fail);
|
||||
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
+3
-1
@@ -19,6 +19,7 @@ extern Suite *clock_suite(void);
|
||||
extern Suite *seq_suite(void);
|
||||
extern Suite *sat_math_suite(void);
|
||||
extern Suite *timers_suite(void);
|
||||
extern Suite *mbuf_suite(void);
|
||||
|
||||
static suite_func suites[] = {
|
||||
bitvec_suite,
|
||||
@@ -33,7 +34,8 @@ static suite_func suites[] = {
|
||||
clock_suite,
|
||||
seq_suite,
|
||||
sat_math_suite,
|
||||
timers_suite
|
||||
timers_suite,
|
||||
mbuf_suite
|
||||
};
|
||||
|
||||
int
|
||||
|
||||
Reference in New Issue
Block a user