Files
Frame-rate-optimization/Middlewares/circular_buffer.c

285 lines
7.7 KiB
C
Raw Normal View History

2026-04-09 10:14:20 +08:00
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "circular_buffer.h"
#include "priv_malloc.h"
/**
* @brief Check if Num is power of 2
*
* @param[in] Num the number to check
*
* @return 1 if Num is power of 2
*/
unsigned long long IsPowerOf2(unsigned long long Num) {
return (Num > 0 && !(Num & (Num - 1)));
}
/**
* @brief calculate the minimum number that round up to the next power of 2
*
* @param[in] Num the number to calculate
*
* @return the number that round up to the next power of 2 (0x100 if Num is 0xf0, 0x81, 0xa3 ... )
*/
unsigned long RoundUp_PowerOf2(unsigned long Num) {
unsigned long result = 1;
if (IsPowerOf2(Num) || Num == 0)
return Num;
else if (Num > LONG_MAX)
return (LONG_MAX ^ ULONG_MAX); // WARN: if Num biger than (LONG_MAX+1) then result will equals to (LONG_MAX+1)
while (Num) {
Num >>= 1;
result <<= 1;
}
return result;
}
/**
* @brief calculate the minimum number that round down to the next power of 2
*
* @param[] Num the number to check
*
* @return the number that round up to the last power of 2 (4 if Num is 5,6,7, 8 if Num is 9,10,11 ... )
*/
unsigned long RoundDown_PowerOf2(unsigned long Num) {
unsigned long result = 1;
if (IsPowerOf2(Num) || Num == 0)
return Num;
else if (Num > LONG_MAX)
return (LONG_MAX ^ ULONG_MAX); // WARN: if Num biger than (LONG_MAX+1) then result will equals to (LONG_MAX+1)
while (Num) {
Num >>= 1;
result <<= 1;
}
return result >> 1;
}
/**
* @brief Init the Circular buffer with a array
*
* @param[in] CBuf The circular buffer to initial
* @param[in] Buff the buffer for circular buffer to store data
* @param[in] Size the size of buffer
*
* @return the Round Down(Power Of 2) size that the circular buffer to be used
*/
int CircBuf_Init(CircBuf_t *CBuf, unsigned char *Buff, unsigned int Size) {
CBuf->Buffer = Buff;
if(!IsPowerOf2(Size)) {
if (Size > INT_MAX)
Size = (INT_MAX ^ UINT_MAX);
else
Size = (int) RoundDown_PowerOf2(Size);
}
CBuf->Size = Size;
CBuf->Tailer = 0;
CBuf->Header = 0;
return Size;
}
/**
* @brief Circular Buffer initialization
*
* @param[in] CBuf the circular buffer to initialization
* @param[in] Size size of the circular buffer
*
* @return 1 if memery allocation success
* 0 if fail
*/
int CircBuf_Alloc(CircBuf_t *CBuf, unsigned int Size) {
int result = 0;
if(!IsPowerOf2(Size)) {
if(Size > INT_MAX)
Size = (INT_MAX ^ UINT_MAX);
else
Size = (int)RoundUp_PowerOf2(Size);
}
CBuf->Buffer = (unsigned char *) board_calloc(Size); // Buffer will set to 0
CBuf->Tailer = 0;
CBuf->Header = 0;
if(CBuf->Buffer != NULL) {
CBuf->Size = Size;
result = 1;
}
return result;
}
/**
* @brief delete circular buffer and release the memery
*
* @param[in] CBuf the circular buffer to delete
*/
void CircBuf_Free(CircBuf_t *CBuf) {
free(CBuf->Buffer);
CBuf = NULL;
}
/**
* @brief put data into the circular buffer
*
* @param[in] CBuf the circular buffer that will store the data
* @param[in] data the data to store into circular buffer
* @param[in] LenToPush the length of data to store into circular buffer
*
* @return the actual size stored into circular buffer
*/
unsigned int CircBuf_Push(CircBuf_t *CBuf, unsigned char *data, unsigned int LenToPush) {
unsigned int len;
LenToPush = MIN(LenToPush, (CBuf->Size - (CBuf->Header - CBuf->Tailer)));
len = MIN(LenToPush, CBuf->Size - (CBuf->Header & (CBuf->Size - 1)));
memcpy(CBuf->Buffer + (CBuf->Header & CBuf->Size - 1), data, len);
memcpy(CBuf->Buffer, data + len, LenToPush - len);
CBuf->Header += LenToPush;
return LenToPush;
}
/**
* @brief get data from circular buffer
*
* @param[in] CBuf the circular buffer that stored data
* @param[in] data target buffer that will store the data that from circular buffer
* @param[in] LenToPop the length that wan't to get from circular buffer
*
* @return actual length that get from circular buffer
*/
unsigned int CircBuf_Pop(CircBuf_t *CBuf, unsigned char *data, unsigned int LenToPop) {
unsigned int len;
LenToPop = MIN(LenToPop, CBuf->Header - CBuf->Tailer);
len = MIN(LenToPop, CBuf->Size - (CBuf->Tailer & (CBuf->Size - 1)));
memcpy(data, CBuf->Buffer + (CBuf->Tailer & (CBuf->Size - 1)), len);
memcpy(data + len, CBuf->Buffer, LenToPop - len);
CBuf->Tailer += LenToPop;
return LenToPop;
}
/**
* @brief get one char from circular buffer
*
* @param[in] CBuf the circular buffer that stored data
* @param[n] data target buffer that will store the data that from circular buffer
*
* @return actual length that get from circular buffer
*/
unsigned int CircBuf_PopOneChar(CircBuf_t *CBuf, unsigned char *data) {
return CircBuf_Pop(CBuf, data, 1);
}
/**
* @brief for access data at Tailer + offset
*
* @param[in] CBuf the circular buffer that stored data
* @param[in] offset the offset of Tailer
*
* @return the data at Buffer[Tailer + offset]
*/
unsigned char CircBuf_At(CircBuf_t *CBuf, unsigned int offset) {
unsigned int index = (CBuf->Tailer + offset) & (CBuf->Size - 1);
return CBuf->Buffer[index];
}
/**
* @brief get data from circular buffer
*
* @param[in] CBuf the circular buffer that stored data
* @param[in] data target buffer that will store the data that from circular buffer
* @param[in] LenToRead the length that wan't to get from circular buffer
*
* @return actual length that get from circular buffer
*/
unsigned int CircBuf_Read(CircBuf_t *CBuf, unsigned char *data, unsigned int LenToRead) {
unsigned int len;
LenToRead = MIN(LenToRead, CBuf->Header - CBuf->Tailer);
len = MIN(LenToRead, CBuf->Size - (CBuf->Tailer & (CBuf->Size - 1)));
memcpy(data, CBuf->Buffer + (CBuf->Tailer & (CBuf->Size - 1)), len);
memcpy(data + len, CBuf->Buffer, LenToRead - len);
return LenToRead;
}
/**
* @brief drop the the size of data at tailer
*
* @param[in] CBuf the circular buffer that stored data
* @param[in] LenToDrop the size of data at tailer of circular_buffer to drop
*/
void CircBuf_Drop(CircBuf_t *CBuf, unsigned int LenToDrop) {
if((CBuf->Tailer + LenToDrop) <= CBuf->Header )
CBuf->Tailer += LenToDrop;
else
CBuf->Tailer = CBuf->Header;
}
/**
* @brief get the Available memery size of circular buffer
*
* @param[in] CBuf the circular buffer to get size
*
* @return Available size of the circular buffer
*/
unsigned int CircBuf_GetAvalaibleSize(CircBuf_t *CBuf) {
return ((CBuf->Size > 0) ? (CBuf->Size - (CBuf->Header - CBuf->Tailer)) : 0);
}
/**
* @brief get the used memery size of circular buffer
*
* @param[in] CBuf the circular buffer to get size
*
* @return used size of the circular buffer
*/
unsigned int CircBuf_GetUsedSize(CircBuf_t *CBuf) {
return (CBuf->Header - CBuf->Tailer);
}
/**
* @brief check if the circular buffer is empty
*
* @param[in] CBuf the circular buffer to check
*
* @return 1 if no data stored in the circular buffer
* 0 if the size of circular buffer equals to 0
* or some data stored in the circular buffer
*/
unsigned int CircBuf_IsEmpty(CircBuf_t *CBuf) {
return ((CBuf->Size > 0) && (CBuf->Header == CBuf->Tailer));
}
/**
* @brief check if the circular buffer is full
*
* @param[in] CBuf the circular buffer to check
*
* @return 1 if the size of circular buffer equals to 0
* or no Available space of circular buffer
*/
unsigned int CircBuf_IsFull(CircBuf_t *CBuf) {
return ((CBuf->Size == 0) || (CBuf->Size == (CBuf->Header - CBuf->Tailer)));
}