环形缓冲区的实现

环形缓冲区

//缓存区大小
#define PM_BUF_SIZE 1024

//获取当前缓冲区的数据个数
#define circ_cnt(head, tail, size) (((head) > (tail)) ? \
		((head) - (tail)) : \
		((head) - (tail)) & ((size) - 1))

//计算缓冲区的可写大小
#define circ_space(head, tail, size) circ_cnt((tail), ((head) + 1), (size))

//把指针n移动1个位置
#define circ_inc(n, s) (((n) + 1) % (s))

//把指针n移动v个位置
#define circ_add(n, v, s) (((n) + (v)) % (s))

//返回小的数
#define min(a, b)              \
    ({                         \
        typeof(a) __a = (a);   \
        typeof(b) __b = (b);   \
        __a < __b ? __a : __b; \
    })

int GetData(char* buff, int pwr, int &prd, char *bufret, int size)
{
	int pr = prd, i = 0;
	char *tmpx= bufret;
	char ch = '\0';
	int bitflag = 0;
	int cnt = 0;

	*bufret = 0;

    
	while (circ_cnt(pwr, pr, PM_BUF_SIZE) > 0) {

		ch = buff[pr];
        //pr指针指向下一个位置
		pr = circ_inc(pr, PM_BUF_SIZE);  // 读指针超出环形缓冲区末尾,会返回头部
		switch(ch)
		{
            //假设S为数据头
			case 'S':			
			bitflag = 1;
			bufret[i++] = ch;
			break;
			
            //假设E为数据尾
			case 'E':
				if ((bitflag & 0x1) == 0x1) {
					bitflag |= 0x2;
					bufret[i++] = ch;
				}
				break;
             
            //只有当接收到数据头时,将有效数据写入bufert中
			default:
			if (bitflag & 0x1) {
				bufret[i++] = ch;
			}
			break;
		}
		
		if (i >= size)
			break;

		if (bitflag & 0x3) {
			break;
		}
	}
	
	if ((bitflag & 0x3) == 0x3) {
        //进入这里就表示接收到了一段有效的数据
		prd = pr;
		bufret[i++] = 0;
		return 1;
	} else {	
		return 0;
	}
}

void RingBufferLoop()
{
    int pw = 0; //写指针
	int pr = 0; //读指针
    char p_buf[PM_BUF_SIZE];
	int ret;
	char temp[128] = {0};

    while(1) {
        // * min(circ_space(pw, pr, PM_BUF_SIZE), (PM_BUF_SIZE - pw))的
        // * 作用就是计算出缓冲区可写的大小。
      ret = read(fd, &p_buf[pw], min(circ_space(pw, pr, PM_BUF_SIZE), (PM_BUF_SIZE - pw)));  
      if(ret > 0)
      {
          //接收到了数据
          //把pw指向最后一个字符
          pw = circ_add(pw, ret, PM_BUF_SIZE);
          
          //在结尾添加\0
          p_buf[circ_inc(pw, PM_BUF_SIZE)] = '\0';   
      }
        
       //检查缓冲区中是否有数据,如果有就处理
      while (circ_cnt(pw, pr, PM_BUF_SIZE) > 0)
      {
          //将有效数据段放入temp中
          ret = GetData(p_buf, pw, pr, temp, sizeof(temp));
          if(!ret)
             break; //当前没有有效数据段
          
          processbuf(temp); //处理有效数据temp
      }
        
    }
    
}
原文地址:https://www.cnblogs.com/r1chie/p/15630296.html