目录
类设计理念
类设计接口函数
类设计函数实现
测试
正常读取与写入
相同类型拷贝
扩容测试
按行读取
类设计理念
类设计接口函数
#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