如下所示,准备两个宏,一个定义类型,一个定义容器大小。
使用时只要先定义这两个宏,然后再包含容器头文件就能生成不同类型和大小的容器了。但是这种方法只允许在源文件中使用,如果在头文件中使用,定义不同类型和大小的容器时会引起宏定义冲突。
#pragma once
#include "cb/cb_define.h"
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#ifdef __cplusplus
extern "C"
{
#endif
///
/// @brief 模板参数。队列元素类型。
///
#ifndef __template_cb_circle_deque_element_type
#define __template_cb_circle_deque_element_type int
#endif
///
/// @brief 模板参数。队列大小。
///
#ifndef __template_cb_circle_deque_size
#define __template_cb_circle_deque_size 100
#endif
///
/// @brief 循环队列。
///
typedef struct cb_circle_deque
{
__template_cb_circle_deque_element_type _buffer[__template_cb_circle_deque_size];
uint32_t _begin;
uint32_t _end;
bool _is_full;
} cb_circle_deque;
///
/// @brief 初始化。
///
/// @param self
/// @return
///
__cb_force_inline void cb_circle_deque_initialize(cb_circle_deque *self)
{
self->_begin = 0;
self->_end = 0;
self->_is_full = false;
}
///
/// @brief 队列中的元素个数。
///
/// @param self
/// @return
///
__cb_force_inline int cb_circle_deque_count(cb_circle_deque *self)
{
if (self->_is_full)
{
return __template_cb_circle_deque_size;
}
if (self->_end >= self->_begin)
{
return self->_end - self->_begin;
}
return __template_cb_circle_deque_size - (self->_begin - self->_end);
}
///
/// @brief 队列为空。
///
/// @param self
/// @return
///
__cb_force_inline bool cb_circle_deque_is_empty(cb_circle_deque *self)
{
return self->_begin == self->_end && !self->_is_full;
}
///
/// @brief 向队列末尾添加元素。
///
/// @param self
/// @param value
/// @return 添加成功返回 true, 添加失败返回 false.
///
__cb_force_inline bool cb_circle_deque_push_back(cb_circle_deque *self,
__template_cb_circle_deque_element_type *value)
{
if (value == NULL)
{
return false;
}
if (self->_is_full)
{
return false;
}
self->_buffer[self->_end] = *value;
self->_end = (self->_end + 1) % __template_cb_circle_deque_size;
if (self->_end == self->_begin)
{
self->_is_full = true;
}
return true;
}
///
/// @brief 向队列头部添加元素。
///
/// @param self
/// @param value
/// @return 添加成功返回 true, 添加失败返回 false.
///
__cb_force_inline bool cb_circle_deque_push_front(cb_circle_deque *self,
__template_cb_circle_deque_element_type *value)
{
if (value == NULL)
{
return false;
}
if (self->_is_full)
{
return false;
}
self->_begin = (self->_begin + __template_cb_circle_deque_size - 1) % __template_cb_circle_deque_size;
self->_buffer[self->_begin] = *value;
if (self->_end == self->_begin)
{
self->_is_full = true;
}
return true;
}
///
/// @brief 弹出队列末尾元素。
///
/// @param self
/// @param out
/// @return
///
__cb_force_inline bool cb_circle_deque_pop_back(cb_circle_deque *self,
__template_cb_circle_deque_element_type *out)
{
if (cb_circle_deque_is_empty(self))
{
return false;
}
self->_end = (self->_end + __template_cb_circle_deque_size - 1) % __template_cb_circle_deque_size;
if (out != NULL)
{
*out = self->_buffer[self->_end];
}
self->_is_full = false;
return true;
}
///
/// @brief 弹出队列头部元素。
///
/// @param self
/// @param out
/// @return
///
__cb_force_inline bool cb_circle_deque_pop_front(cb_circle_deque *self,
__template_cb_circle_deque_element_type *out)
{
if (cb_circle_deque_is_empty(self))
{
return false;
}
if (out != NULL)
{
*out = self->_buffer[self->_begin];
}
self->_begin = (self->_begin + 1) % __template_cb_circle_deque_size;
self->_is_full = false;
return true;
}
///
/// @brief 获取队列中指定索引的元素。
///
/// @param self
/// @param index
///
/// @return 如果指定索引处有元素,则返回该元素的指针,否则返回空指针。
///
__cb_force_inline __template_cb_circle_deque_element_type *cb_circle_deque_get(cb_circle_deque *self,
int index)
{
if (index < 0 || index >= cb_circle_deque_count(self))
{
return NULL;
}
uint32_t pos = (self->_begin + index) % __template_cb_circle_deque_size;
return &self->_buffer[pos];
}
///
/// @brief 清空队列。
///
/// @param self
/// @return
///
__cb_force_inline void cb_circle_deque_clear(cb_circle_deque *self)
{
self->_begin = 0;
self->_end = 0;
self->_is_full = false;
}
#ifdef __cplusplus
}
#endif