Buffer缓冲区类设计实现

目录

类设计理念

类设计接口函数

类设计函数实现

测试

正常读取与写入

相同类型拷贝

扩容测试

按行读取


类设计理念

类设计接口函数

#include <vector>
#include <cstdint>#define BUFFER_DEFAULT_SIZE 1024    // Buffer 默认起始大小
class Buffer
{
private:std::vector<char> _buffer; // 使用vector进行内存空间管理uint64_t _reader_idx;      // 读偏移uint64_t _writer_idx;      // 写偏移
public:Buffer() : _reader_idx(0), _writer_idx(0), _buffer(BUFFER_DEFAULT_SIZE) {}// 获取当前写入起始地址void *WirtePosition();// 获取当前读取起始地址void *ReadPosition();// 获取缓冲区末尾空闲空间大小--写偏移之后的空闲空间uint64_t TailIdleSize();// 获取缓冲区起始空闲空间大小--读偏移之前的空闲空间uint64_t HeadIdleSize();// 获取可读数据大小uint16_t ReadAbleSize();// 将读偏移向后移动void MoveReadOffset(uint64_t len);// 将写偏移向后移动void MoveWriteOffset(uint64_t len);// 确保可写空间足够(整体空闲空间够了就移动数据。否则就扩容)void EnsureWriteSpace(uint64_t len);// 写入数据void Write(void *data, uint64_t len);// 读取数据void Read(void *buf, uint64_t len);// 清空缓冲区void Clear();
};

类设计函数实现

#include <iostream>
#include <vector>
#include <cstdint>
#include <cassert>
#include <string>
#include <cstring>#define BUFFER_DEFAULT_SIZE 1024 // Buffer 默认起始大小
class Buffer
{
private:std::vector<char> _buffer; // 使用vector进行内存空间管理uint64_t _reader_idx;      // 读偏移uint64_t _writer_idx;      // 写偏移
public:Buffer() : _reader_idx(0), _writer_idx(0), _buffer(BUFFER_DEFAULT_SIZE) {}char *Begin() { return &*_buffer.begin(); }// 获取当前写入起始地址char *WirtePosition() { return Begin() + _writer_idx; }// 获取当前读取起始地址char *ReadPosition() { return Begin() + _reader_idx; }// 获取缓冲区末尾空闲空间大小--写偏移之后的空闲空间, 总体空间大小减去写偏移uint64_t TailIdleSize() { return _buffer.size() - _writer_idx; }// 获取缓冲区起始空闲空间大小--读偏移之前的空闲空间uint64_t HeadIdleSize() { return _reader_idx; }// 获取可读数据大小 = 写偏移 - 读偏移uint16_t ReadAbleSize() { return _writer_idx - _reader_idx; };// 将读偏移向后移动void MoveReadOffset(uint64_t len){// 向后移动的大小, 必须小于可读数据大小assert(len <= ReadAbleSize());_reader_idx += len;}// 将写偏移向后移动void MoveWriteOffset(uint64_t len){// 向后移动的大小,必须小于当前后边的空闲空间大小assert(len <= TailIdleSize());_writer_idx += len;}// 确保可写空间足够(整体空闲空间够了就移动数据,否则就扩容)void EnsureWriteSpace(uint64_t len){// 如果末尾空闲空间大小足够,直接返回if (len <= TailIdleSize()){return;}// 末尾空闲空间不够,则判断加上起始位置的空闲空间大小是否足够,够了就将数据移动到起始位置if (len <= TailIdleSize() + HeadIdleSize()){// 将数据移动到起始位置uint64_t rsz = ReadAbleSize();                            // 把当前数据大小先保存起来std::copy(ReadPosition(), ReadPosition() + rsz, Begin()); // 把可读数据拷贝到起始位置_reader_idx = 0;                                          // 将读偏移归0_writer_idx = rsz;                                        // 将写位置置为可读数据大小, 因为当前的可读数据大小就是写偏移量}else{// 总体空间不够,则需要扩容,不移动数据,直接给写偏移之后扩容足够空间即可_buffer.resize(_writer_idx + len);}}// 写入数据void Write(const void *data, uint64_t len){// 1.保证有足够空间, 2.拷贝数据进去EnsureWriteSpace(len);const char *d = (const char *)data;std::copy(d, d + len, WirtePosition());}void WirteAndPush(const void *data, uint64_t len){Write(data, len);MoveWriteOffset(len);}void WriteString(const std::string &data){return Write(data.c_str(), data.size());}void WriteStringAndPush(const std::string &data){WriteString(data);MoveWriteOffset(data.size());}void WriteBuffer(Buffer &data){return Write(data.ReadPosition(), data.ReadAbleSize());}void WirteBufferAndPush(Buffer &data){WriteBuffer(data);MoveWriteOffset(data.ReadAbleSize());}// 读取数据void Read(void *buf, uint64_t len){// 要求获取的数据大小必须小于可读数据大小assert(len <= ReadAbleSize());std::copy(ReadPosition(), ReadPosition() + len, (char*)buf);}void ReadAndPop(void *buf, uint64_t len){Read(buf, len);MoveReadOffset(len);}std::string ReadAsString(uint64_t len){// 要求获取的数据大小必须小于可读数据大小assert(len <= ReadAbleSize());std::string str;str.resize(len);Read(&str[0], len); // 这里不直接用str.c_str()的原因是,这个的返回值是const类型return str;}std::string ReadAsStringAndPop(uint64_t len){assert(len <= ReadAbleSize());std::string str = ReadAsString(len);MoveReadOffset(len);return str;}char *FindCRLF(){char *res = (char*)memchr(ReadPosition(), '\n', ReadAbleSize());return res;}//这种情况针对的是,通常获取一行数据std::string GetLine(){char *pos = FindCRLF();if(pos == nullptr)return "";// +1 是为了把换行字符也取出来return ReadAsString(pos - ReadPosition() + 1);}std::string GetLineAndPop(){std::string str = GetLine();MoveReadOffset(str.size());return str;}// 清空缓冲区void Clear(){// 只需要将偏移量归0即可_reader_idx = 0;_writer_idx = 0;}
};

测试

正常读取与写入

符合预期

相同类型拷贝

符合预期

扩容测试

符合预期

按行读取

程序正常退出,符合预期(不符合会死循环)

最后附上makefile

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/443539.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode —— 137. 只出现一次的数字 II

&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️Take your time ! &#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️…

一二三应用开发平台文件处理设计与实现系列之7——minio多节点共享磁盘模式验证

背景 在不了解minio架构设计之前&#xff0c;我根据既往经验推测minio是将文件读写封装实现了一个应用系统&#xff0c;如要实现高可用&#xff0c;则需要部署两个minio节点&#xff0c;共享同一块磁盘。两个minio节组成一个集群&#xff0c;使用nginx实现负载均衡&#xff0c…

Python下载安装与环境配置

本文将指导您完成Python的下载、安装以及环境配置过程&#xff0c;确保您在编写和运行Python代码时能够获得最佳体验。我们将提供详细的步骤和代码示例&#xff0c;帮助您顺利完成设置。 一、Python下载与安装 访问Python官网&#xff1a;首先&#xff0c;您需要访问Python的官…

通俗易懂三大范式

通俗易懂三大范式 第一范式说的是每个字段不可再分 第二范式说的是不能存在部分依赖&#xff08;不能由联合主键的部分就可以推出其他字段&#xff0c;必须整个联合主键才能推出其他字段&#xff09; 第三范式说的是不能存在间接依赖(A&#xff08;主键&#xff09;→B,B→C…

学习嵌入式第十五天之结构体

用变量a给出下面的定义 a) 一个整型数&#xff08;An integer&#xff09; //int a;b) 一个指向整型数的指针&#xff08;A pointer to an integer&#xff09; //int *a;c) 一个指向指针的的指针&#xff0c;它指向的指针是指向一个整型数&#xff08;A pointer to a poin…

前端Web开发

安装flask框架 pip install flask 导入flask模块 from flask import Flask 【可能遇到的问题】 出现了如下警告&#xff1a; WARNING: You are using pip version 21.2.4; however, version 22.0.4 is available.You should consider upgrading via the D:\Python\python…

【Tomcat与网络2】一文理解Servlet是怎么工作的

在前面&#xff0c;我们研究了如何用idea来启动一个Servlet程序&#xff0c;今天我们就再来看一下Servlet是如何工作的。 目录 1.Servlet 介绍 2.Servlet 容器工作过程 3.Servlet的扩展 不管是电脑还是手机浏览器&#xff0c;发给服务端的就是一个 HTTP 格式的请求&#xf…

力扣hot100 划分字母区间 贪心 思维 满注释版

Problem: 763. 划分字母区间 文章目录 思路复杂度Code 思路 &#x1f468;‍&#x1f3eb; 代码随想录 复杂度 时间复杂度: O ( n ) O(n) O(n) 空间复杂度: O ( n ) O(n) O(n) Code class Solution {public List<Integer> partitionLabels(String s){// 创建哈希…

基于SpringBoot的高校社团管理系统

末尾获取源码作者介绍&#xff1a;大家好&#xff0c;我是何时&#xff0c;本人4年开发经验&#xff0c;专注定制项目开发 更多项目&#xff1a;CSDN主页YAML 我欲乘风归去 又恐琼楼玉宇 高处不胜寒 -苏轼 目录 一、项目简介 二、开发技术与环境配置 2.1 SpringBoot框架 2…

Activiti工作流引擎

一、工作流介绍&#xff1a; 1.1 概念&#xff1a; 工作流(Workflow)&#xff0c;就是通过计算机对业务流程自动化执行管理。它主要解决的是“使在多个参与者之间按照某种预定义的规则自动进行传递文档、信息或任务的过程&#xff0c;从而实现某个预期的业务目标&#xff0c;或…

CRM系统能为企业解决5大痛点

客户关系管理&#xff08;CRM&#xff09;系统是企业最有价值的工具之一&#xff0c;但也可能是管理最复杂的工具之一。如果运用得当&#xff0c;CRM系统将帮助企业提高效率&#xff0c;实现增长。一项研究报告指出&#xff0c;客户关系管理工具可将销售额提高 29%&#xff0c;…

LoadRunner从零开始之LoadRunner脚本语言基础

在用LoadRunner 做性能测试的过程中&#xff0c;编写脚本是 一项非常重要的工作。不夸张地说&#xff0c;一个脚本的好坏关系到性能测试的成败。“ 工欲善其事&#xff0c;必先利其器” &#xff0c; 在本章我们将学习LoadRunner 脚本语言以及脚本的开发技巧。 下面 我 们 要 通…