#ifndef _PBUF_H #define _PBUF_H #include <stdint.h> #include <stddef.h> #include <stdbool.h> #include <assert.h> #include <string.h> #ifdef __cplusplus extern "C" { #endif typedef void (*pbuf_callback_t)(void); //function pointer that will be called when a pbuf is freed in this pool struct pbuf_pool_s; typedef struct pbuf_s { uint8_t* payload; uint32_t length; uint32_t capacity; uint8_t* payload_memory; struct pbuf_s *next; //used to link pbufs struct pbuf_pool_s *pool; void *user; }pbuf_t; typedef struct pbuf_pool_s { pbuf_t* pbuf_memory; uint32_t pbuf_count; uint8_t* payload_memory; uint32_t payload_capacity; uint32_t pbufs_available; pbuf_t* free_list; pbuf_callback_t free_callback; }pbuf_pool_t; #define PBUF_DECLARE_POOL(pool_name, pbuf_count, pbuf_size) \ static uint8_t pool_name##_payload_memory[(pbuf_count) * (((pbuf_size) + 3) & ~3)] __attribute__((aligned(4))); \ static pbuf_t pool_name##_memory[pbuf_count]; \ pbuf_pool_t pool_name #define STATIC_PBUF_DECLARE_POOL(pool_name, pbuf_count, pbuf_size) \ static uint8_t pool_name##_payload_memory[(pbuf_count) * (((pbuf_size) + 3) & ~3)] __attribute__((aligned(4))); \ static pbuf_t pool_name##_memory[pbuf_count]; \ static pbuf_pool_t pool_name #define PBUF_INIT_POOL(pool_name) \ pbuf_pool_create(&pool_name, \ sizeof(pool_name##_memory) / sizeof(pbuf_t), \ pool_name##_memory, \ sizeof(pool_name##_payload_memory) / (sizeof(pool_name##_memory) / sizeof(pbuf_t)), \ pool_name##_payload_memory) /** \brief Creates a new pool of pbufs \param pool Pointer to a pbuf_pool_t structure that will be initialized \param pbuf_count Number of pbufs to create in the pbuf pool \param pbuf_memory Pointer to a statically allocated area of memory for storing the pbuf structures. \param payload_capacity Size of the pbuf payload. \param payload_memory Pointer to statically allocated memory that will be used for storing the pbuf attached buffers pbuf_memory needs to be a statically allocated memory chunk of size: pbuf_count * sizeof(pbuf_t) (bytes) payload_memory needs to be a statically allocated memory chunk of size: pbuf_count * pbuf_payload_size (bytes) */ void pbuf_pool_create(pbuf_pool_t *pool, uint32_t pbuf_count, void *pbuf_memory, uint32_t payload_capacity, void *payload_memory); void pbuf_pool_reset(pbuf_pool_t *pool); void pbuf_dump_pool(pbuf_pool_t *pool); static inline uint32_t pbuf_pool_get_available(pbuf_pool_t *pool) { return pool->pbufs_available; } static inline void pbuf_reset(pbuf_t *p) { p->payload = p->payload_memory; p->capacity = p->pool->payload_capacity; } static inline uint32_t pbuf_offset(pbuf_t *p) { return p->payload - p->payload_memory; } static inline pbuf_t* pbuf_alloc(pbuf_pool_t *pool) { assert(pool); pbuf_t* p = pool->free_list; if (p) { pool->free_list = pool->free_list->next; //remove it from the list pool->pbufs_available--; pbuf_reset(p); } return p; } static inline void pbuf_free(pbuf_t* p) { if (p) { p->next = p->pool->free_list; //add it back to the free list p->pool->free_list = p; p->pool->pbufs_available++; if (p->pool->free_callback) //call the hook if we have one p->pool->free_callback(); } } static inline void pbuf_free_queue(pbuf_t* queue) { while(queue) { pbuf_t *p = queue; queue = queue->next; pbuf_free(p); } } static inline bool pbuf_insert_uint8(pbuf_t* p, uint8_t value) { if ((p->length + sizeof(value)) > p->capacity) return false; *p->payload++ = value; p->length += sizeof(value); return true; } static inline bool pbuf_insert_uint16(pbuf_t* p, uint16_t value) { if ((p->length + sizeof(value)) > p->capacity) return false; *p->payload++ = value; *p->payload++ = value >> 8; p->length += sizeof(value); return true; } static inline bool pbuf_insert_uint32(pbuf_t* p, uint32_t value) { if ((p->length + sizeof(value)) > p->capacity) return false; *p->payload++ = value; *p->payload++ = value >> 8; *p->payload++ = value >> 16; *p->payload++ = value >> 24; p->length += sizeof(value); return true; } static inline bool pbuf_insert_uint64(pbuf_t* p, uint64_t value) { if ((p->length + sizeof(value)) > p->capacity) return false; *p->payload++ = value; *p->payload++ = value >> 8; *p->payload++ = value >> 16; *p->payload++ = value >> 24; *p->payload++ = value >> 32; *p->payload++ = value >> 40; *p->payload++ = value >> 48; *p->payload++ = value >> 56; p->length += sizeof(value); return true; } static inline bool pbuf_insert_float(pbuf_t* p, float value) { if ((p->length + sizeof(value)) > p->capacity) return false; memcpy(p->payload, &value, sizeof(value)); p->payload += sizeof(value); p->length += sizeof(value); return true; } static inline bool pbuf_insert_double(pbuf_t* p, double value) { if ((p->length + sizeof(value)) > p->capacity) return false; memcpy(p->payload, &value, sizeof(value)); p->payload += sizeof(value); p->length += sizeof(value); return true; } static inline bool pbuf_insert_data(pbuf_t* p, const void* data, size_t size) { if ((p->length + size) > p->capacity) return false; memcpy(p->payload, data, size); p->payload += size; p->length += size; return true; } static inline bool pbuf_extract_uint8(pbuf_t* p, uint8_t* value) { if (p->length < sizeof(uint8_t)) return false; *value = *p->payload++; p->length -= sizeof(uint8_t); return true; } static inline bool pbuf_extract_uint16(pbuf_t* p, uint16_t* value) { if (p->length < sizeof(uint16_t)) return false; *value = ((uint16_t)p->payload[1] << 8) + p->payload[0]; p->payload += sizeof(uint16_t); p->length -= sizeof(uint16_t); return true; } static inline bool pbuf_extract_uint32(pbuf_t* p, uint32_t* value) { if (p->length < sizeof(uint32_t)) return false; *value = ((uint32_t)p->payload[3] << 24) + ((uint32_t)p->payload[2] << 16) + ((uint32_t)p->payload[1] << 8) + p->payload[0]; p->payload += sizeof(uint32_t); p->length -= sizeof(uint32_t); return true; } static inline bool pbuf_extract_uint64(pbuf_t* p, uint64_t* value) { if (p->length < sizeof(uint64_t)) return false; *value = ((uint64_t)p->payload[7] << 56) + ((uint64_t)p->payload[6] << 48) + ((uint64_t)p->payload[5] << 40) + ((uint64_t)p->payload[4] << 32) + ((uint32_t)p->payload[3] << 24) + ((uint32_t)p->payload[2] << 16) + ((uint32_t)p->payload[1] << 8) + p->payload[0]; p->payload += sizeof(uint64_t); p->length -= sizeof(uint64_t); return true; } static inline bool pbuf_extract_float32(pbuf_t* p, float* value) { if (p->length < sizeof(float)) return false; memcpy(value, p->payload, sizeof(float)); p->payload += sizeof(float); p->length -= sizeof(float); return true; } static inline bool pbuf_extract_data(pbuf_t* p, void* data, size_t size) { if (p->length < size) return false; memcpy(data, p->payload, size); p->payload += size; p->length -= size; return true; } static inline bool pbuf_extract_pointer(pbuf_t* p, void** data, size_t size) { if (p->length < size) return false; *data = p->payload; p->payload += size; p->length -= size; return true; } #ifdef __cplusplus } #endif #endif