202 lines
6.1 KiB
C
202 lines
6.1 KiB
C
#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 {
|
|
/** prev/next pointer, user can use this for a linked list*/
|
|
struct MBuf *prev;
|
|
struct MBuf *next;
|
|
/** Pointers the user can use to remember spots in
|
|
* the data. (these must either be NULL pointers or point into
|
|
* something in the buffer*/
|
|
uint8_t *p1;
|
|
uint8_t *p2;
|
|
uint8_t *p3;
|
|
uint8_t *p4;
|
|
/**Arbitary pointer user can associate with the mbuf*/
|
|
void *cookie;
|
|
|
|
/*UC_MBUF_FLAGS. The upper 16 bits can be used by the application */
|
|
uint32_t flags;
|
|
/** Total no of bytes from bufstart*/
|
|
uint32_t allocated;
|
|
/** Start of the buffer*/
|
|
uint8_t *bufstart;
|
|
/** Start of the data in the buffer*/
|
|
uint8_t *head;
|
|
/** End of the buffer (one byte past the data) */
|
|
uint8_t *tail;
|
|
/** Internal data, if we allocate it inline */
|
|
uint8_t inline_data[0];
|
|
};
|
|
|
|
/**
|
|
* Concept:
|
|
* <--------- allocated ----------->
|
|
* <--- len -->
|
|
* +--------------------------------+
|
|
* |Headroom| Data |Tailroom |
|
|
* +--------------------------------+
|
|
* ^ ^ ^
|
|
* | | |
|
|
* | | tail
|
|
* | head
|
|
* bufstart
|
|
*
|
|
* Initially when empty, head == tail, and the length is 0.
|
|
* Data is added to the tail.
|
|
*
|
|
* If head == bufstart, there is no headroom
|
|
* if tail points one past the allocated space, there is no
|
|
* tailroom (the buffer is full)
|
|
*
|
|
* Conventions:
|
|
* push - prepend data to the buffer (in the head room part)
|
|
* (move head to the left)
|
|
* pull - remove data from the beginning of the message.
|
|
* (move head to the right)
|
|
* put - Add data to the buffer.
|
|
* (move tail to the right)
|
|
*/
|
|
|
|
/** Allocate an mbuf with a length and headroom,
|
|
* the buffer will have the flag UC_MBUF_FL_MALLOC
|
|
* The total length of the buffer will be length+headroom
|
|
*
|
|
* @param len the initial length of the mbuf
|
|
* @param the initial headroom of the mbuf
|
|
* @return NULL if the allocation fails
|
|
*/
|
|
struct MBuf *uc_mbuf_new_hr(uint32_t len, uint32_t headroom);
|
|
|
|
/** As uc_mbuf_new_hr, but without any headroom*/
|
|
#define uc_mbuf_new(len) uc_mbuf_new_hr((len), 0)
|
|
|
|
|
|
/** Allocate an mbuf with a length and headroom,
|
|
* the buffer will have the flag UC_MBUF_FL_MALLOC_INLINE
|
|
* The total length of the buffer will be length+headroom
|
|
*
|
|
* @param len the initial length of the mbuf
|
|
* @param the initial headroom of the mbuf
|
|
* @return NULL if the allocation fails
|
|
*/
|
|
struct MBuf *uc_mbuf_new_inline_hr(uint32_t len, uint32_t headroom);
|
|
|
|
/** As uc_mbuf_new_inline_hr, but without any headroom*/
|
|
#define uc_mbuf_new_inline(len) uc_mbuf_new_inline_hr((len), 0)
|
|
|
|
/** @param mbuf the mbuf to free. (passing NULL is a no-op)*/
|
|
void uc_mbuf_free(struct MBuf *mbuf);
|
|
|
|
/** Create a new mbuf, with a copy of the data from the given
|
|
* mbuf. The new mbuf will have the same headroom as the old one,
|
|
* but no tailroom.
|
|
*
|
|
* @param mbuf mbuf to copy
|
|
*/
|
|
struct MBuf *uc_mbuf_copy_data(struct MBuf *mbuf);
|
|
|
|
/** Initialize an mbuf. This function is mostly used internally,
|
|
* but can be used to e.g. create an mbuf based on a local array
|
|
* (in which case UC_MBUF_FL_STATIC must be set), or other data
|
|
* whose memory is already allocated.
|
|
*
|
|
* The whole buffer must have len + headroom available data
|
|
*
|
|
* @param mbuf to initialise
|
|
* @param buf start of the buffer
|
|
* @param len length of the buffer (not including the headroom)
|
|
* @param headroom the headroom in the buffer
|
|
* @param flags The appropriate UC_MBUF_FLAGS
|
|
*/
|
|
void uc_mbuf_init(struct MBuf *mbuf, uint8_t *buf, uint32_t len, uint32_t headroom, uint32_t flags);
|
|
|
|
/** Zero out all the data in this mbuf, including the headroom
|
|
*
|
|
* @param mbuf mbuf to zero out
|
|
*/
|
|
void uc_mbuf_zero(struct MBuf *mbuf);
|
|
|
|
/**
|
|
* @return the length of the data in this mbuf
|
|
*/
|
|
static UC_INLINE uint32_t uc_mbuf_len(struct MBuf *mbuf)
|
|
{
|
|
return (uint32_t)(mbuf->tail - mbuf->head);
|
|
}
|
|
|
|
/**
|
|
* @return the length of the tailroom in this mbuf
|
|
*/
|
|
static UC_INLINE uint32_t uc_mbuf_tailroom(struct MBuf *mbuf)
|
|
{
|
|
return mbuf->allocated - (uint32_t)(mbuf->tail - mbuf->bufstart);
|
|
}
|
|
|
|
/**
|
|
* @return the length of the headroom in this mbuf
|
|
*/
|
|
static UC_INLINE uint32_t uc_mbuf_headroom(struct MBuf *mbuf)
|
|
{
|
|
return (uint32_t)(mbuf->head - mbuf->bufstart);
|
|
}
|
|
|
|
|
|
/** Append data data to this buffer
|
|
* The returned pointer points at the end of the current
|
|
* data in the buffer, advancing the tail be size bytes .
|
|
* You need to insert the size bytes at in the returned pointer.
|
|
*
|
|
* @param size bytes to put in the buffer
|
|
* @return NULL if the mbuf does not have room for the given size
|
|
*/
|
|
uint8_t *uc_mbuf_put(struct MBuf *mbuf, uint32_t size);
|
|
|
|
/** Prepend data to the buffer. The buffer needs to have enough
|
|
* headroom to allow this.
|
|
* The returned pointer points size bytes in front if the current
|
|
* data in the buffer, retreating the head pointer by size butes
|
|
* You need to insert the size bytes in the returned pointer.
|
|
*
|
|
* @oaram size bytes to prepend to the buffer
|
|
* @return NULL if the mbuf does not have enough headroom
|
|
*/
|
|
uint8_t *uc_mbuf_push(struct MBuf *mbuf, uint32_t size);
|
|
|
|
/** Remove data from the buffer ("read" data from it)
|
|
* The returned pointer is the beginning of the data in the
|
|
* buffer, advancing the head by size bytes.
|
|
*
|
|
* @param size number of bytes to pull
|
|
* @return NULL if the buffer does not have at least size bytes
|
|
**/
|
|
uint8_t *uc_mbuf_pull(struct MBuf *mbuf, uint32_t size);
|
|
|
|
/** Get a pointer to the data of the buffer
|
|
*
|
|
* @return pointer to the start of the data (head)
|
|
*/
|
|
static UC_INLINE uint8_t *uc_mbuf_head(struct MBuf* mbuf)
|
|
{
|
|
return mbuf->head;
|
|
}
|
|
|
|
#undef UC_INLINE
|
|
|
|
#endif
|