-
ANTA authoredbe943222
//
// CircularBuffer.c
//
// Created by 罗亮富(Roen zxllf23@163.com) on 14-1-14.
// Copyright (c) 2014年 All rights reserved.
//
// Note: Edited by Kurotych Anatolii
#include "dap_circular_buffer.h"
#include <string.h>
#include <errno.h>
#include "dap_common.h"
#define LOG_TAG "circular_buffer"
struct s_circularBuffer{
size_t capacity; //capacity bytes size
size_t dataSize; //occupied data size
size_t tailOffset; //head offset, the oldest byte position offset
size_t headOffset; //tail offset, the lastest byte position offset
uint8_t *buffer;
};
extern circular_buffer_t circular_buffer_create(size_t size)
{
size_t totalSize = sizeof(struct s_circularBuffer) + size;
void *p = malloc(totalSize);
circular_buffer_t buffer = (circular_buffer_t)p;
buffer->buffer = p + sizeof(struct s_circularBuffer);
buffer->capacity = size;
circular_buffer_reset(buffer);
return buffer;
}
void circular_buffer_free(circular_buffer_t cBuf)
{
circular_buffer_reset(cBuf);
cBuf->capacity = 0;
cBuf->dataSize = 0;
cBuf->buffer = NULL;
free(cBuf);
}
void circular_buffer_reset(circular_buffer_t cBuf)
{
cBuf->headOffset = -1;
cBuf->tailOffset = -1;
cBuf->dataSize = 0;
}
size_t circular_buffer_get_capacity(circular_buffer_t cBuf)
{
return cBuf->capacity;
}
size_t circular_buffer_get_data_size(circular_buffer_t cBuf)
{
return cBuf->dataSize;
}
void circular_buffer_push(circular_buffer_t cBuf, const void *src, size_t length)
{
if(length == 0)
return;
size_t writableLen = length;
const void *pSrc = src;
if(writableLen > cBuf->capacity)//in case of size overflow
{
size_t overFlowLen = writableLen - cBuf->capacity;
writableLen = cBuf->capacity;
pSrc = src + overFlowLen;
}
bool resetHead = false;
//in case the circle buffer won't be full after adding the data
if(cBuf->tailOffset+writableLen < cBuf->capacity)
{
memcpy(&cBuf->buffer[cBuf->tailOffset + 1], pSrc, writableLen);
if((cBuf->tailOffset < cBuf->headOffset) && (cBuf->tailOffset+writableLen >= cBuf->headOffset) )
resetHead = true;
cBuf->tailOffset += writableLen;
}
else//in case the circle buffer will be overflow after adding the data
{
size_t remainSize = cBuf->capacity - cBuf->tailOffset - 1; //the remain size
memcpy(&cBuf->buffer[cBuf->tailOffset+1], pSrc, remainSize);
size_t coverSize = writableLen - remainSize; //size of data to be covered from the beginning
memcpy(cBuf->buffer, pSrc+remainSize, coverSize);
if(cBuf->tailOffset < cBuf->headOffset)
resetHead = true;
else
{
if(coverSize>cBuf->headOffset)
resetHead = true;
}
cBuf->tailOffset = coverSize - 1;
}
if(cBuf->headOffset == (size_t)-1)
cBuf->headOffset = 0;
if(resetHead)
{
if(cBuf->tailOffset+1 < cBuf->capacity)
cBuf->headOffset = cBuf->tailOffset + 1;
else
cBuf->headOffset = 0;
cBuf->dataSize = cBuf->capacity;
}
else
{
if(cBuf->tailOffset >= cBuf->headOffset)
cBuf->dataSize = cBuf->tailOffset - cBuf->headOffset + 1;
else
cBuf->dataSize = cBuf->capacity - (cBuf->headOffset - cBuf->tailOffset - 1);
}
}
#ifdef __unix__
#include <sys/types.h>
#include <sys/socket.h>
int circular_buffer_write_In_socket(circular_buffer_t cBuf, int sockfd)
{
if(cBuf->dataSize == 0) {
return 0;
}
ssize_t rdLen = -1;
if(cBuf->headOffset <= cBuf->tailOffset)
{
rdLen = send(sockfd,
&cBuf->buffer[cBuf->headOffset],
cBuf->dataSize, MSG_DONTWAIT | MSG_NOSIGNAL | MSG_DONTROUTE);
if(rdLen < 0) {
log_it(L_ERROR, "Can't write data in socket. %s", strerror(errno));
return -1;
}
cBuf->headOffset += rdLen;
if(cBuf->headOffset > cBuf->tailOffset)
{
cBuf->headOffset = -1;
cBuf->tailOffset = -1;
}
cBuf->dataSize -= rdLen;
}
else
{
if(cBuf->headOffset + cBuf->dataSize <= cBuf->capacity)
{
rdLen = send(sockfd,
&cBuf->buffer[cBuf->headOffset],
cBuf->dataSize, MSG_DONTWAIT | MSG_NOSIGNAL);
if(rdLen < 0) {
log_it(L_ERROR, "Can't write data in socket. %s", strerror(errno));
return -1;
}
cBuf->headOffset += rdLen;
if(cBuf->headOffset == cBuf->capacity)
cBuf->headOffset = 0;
}
else
{
size_t countBytesToEnd = cBuf->capacity - cBuf->headOffset;
rdLen = send(sockfd,
&cBuf->buffer[cBuf->headOffset],
countBytesToEnd, MSG_DONTWAIT | MSG_NOSIGNAL);
// log_it(L_DEBUG, "Write in socket: %s", &cBuf->buffer[cBuf->headOffset]);
if(rdLen < 0) {
log_it(L_ERROR, "Can't write data in socket. %s", strerror(errno));
return -1;
}
if(rdLen < (ssize_t)countBytesToEnd) {
log_it(L_WARNING, "rdLen < countBytesToEnd");
circular_buffer_pop(cBuf, rdLen, NULL);
return rdLen;
}
cBuf->dataSize -= countBytesToEnd;
cBuf->headOffset = 0;
cBuf->tailOffset = cBuf->dataSize - 1;
ssize_t rdLen2 = send(sockfd,
cBuf->buffer,
cBuf->dataSize, MSG_DONTWAIT | MSG_NOSIGNAL);
if(rdLen2 < 0) {
log_it(L_ERROR, "Can't write data in socket. %s", strerror(errno));
return rdLen;
}
cBuf->headOffset = rdLen2;
if(cBuf->headOffset > cBuf->tailOffset)
{
cBuf->headOffset = -1;
cBuf->tailOffset = -1;
cBuf->dataSize = 0;
}
return countBytesToEnd + rdLen2;
}
}
return rdLen;
}
#endif
size_t inter_circularBuffer_read(circular_buffer_t cBuf, size_t length, void *dataOut, bool resetHead)
{
if(cBuf->dataSize == 0 || length == 0)
return 0;
size_t rdLen = length;
if(cBuf->dataSize < rdLen)
rdLen = cBuf->dataSize;
if(cBuf->headOffset <= cBuf->tailOffset)
{
if(dataOut)
memcpy(dataOut, &cBuf->buffer[cBuf->headOffset], rdLen);
if(resetHead)
{
cBuf->headOffset += rdLen;
if(cBuf->headOffset > cBuf->tailOffset)
{
cBuf->headOffset = -1;
cBuf->tailOffset = -1;
}
}
}
else
{
if(cBuf->headOffset+rdLen <= cBuf->capacity)
{
if(dataOut)
memcpy(dataOut, &cBuf->buffer[cBuf->headOffset], rdLen);
if(resetHead)
{
cBuf->headOffset += rdLen;
if(cBuf->headOffset == cBuf->capacity)
cBuf->headOffset = 0;
}
}
else
{
size_t frg1Len = cBuf->capacity - cBuf->headOffset;
if(dataOut)
memcpy(dataOut, &cBuf->buffer[cBuf->headOffset], frg1Len);
size_t frg2len = rdLen - frg1Len;
if(dataOut)
memcpy(dataOut+frg1Len, cBuf->buffer, frg2len);
if(resetHead)
{
cBuf->headOffset = frg2len;
if(cBuf->headOffset > cBuf->tailOffset)
{
cBuf->headOffset = -1;
cBuf->tailOffset = -1;
}
}
}
}
if(resetHead)
cBuf->dataSize -= rdLen;
return rdLen;
}
size_t circular_buffer_pop(circular_buffer_t cBuf, size_t length, void *dataOut)
{
return inter_circularBuffer_read(cBuf,length,dataOut,true);
}
size_t circular_buffer_read(circular_buffer_t cBuf, size_t length, void *dataOut)
{
return inter_circularBuffer_read(cBuf,length,dataOut,false);
}
//print circular buffer's content into str,
void circular_buffer_print(circular_buffer_t cBuf, bool hex)
{
uint8_t *b = cBuf->buffer;
size_t cSize = circular_buffer_get_capacity(cBuf);
char *str = malloc(2*cSize+1);
char c;
for(size_t i=0; i<cSize; i++)
{
if(circular_buffer_get_data_size(cBuf) == 0)
{
c = '_';
}
else if (cBuf->tailOffset < cBuf->headOffset)
{
if(i>cBuf->tailOffset && i<cBuf->headOffset)
c = '_';
else
c = b[i];
}
else
{
if(i>cBuf->tailOffset || i<cBuf->headOffset)
c = '_';
else
c = b[i];
}
if(hex)
dap_sprintf(str+i*2, "%02X|",c);
else
dap_sprintf(str+i*2, "%c|",c);
}
printf("CircularBuffer: %s <size %zu dataSize:%zu>\n",str,circular_buffer_get_capacity(cBuf),circular_buffer_get_data_size(cBuf));
free(str);
}