Skip to content

Commit

Permalink
✨ add dynamic buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
markparticle committed Jun 28, 2020
1 parent f578366 commit e1bd71d
Show file tree
Hide file tree
Showing 2 changed files with 201 additions and 0 deletions.
139 changes: 139 additions & 0 deletions code/buffer/buffer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
* @Author : mark
* @Date : 2020-06-26
* @copyleft GPL 2.0
*/
#include "buffer.h"

Buffer::Buffer() : buffer_(INIT_BUFF_SIZE), readPos_(0), writePos_(0) {}

size_t Buffer::ReadableBytes() const {
return writePos_ - readPos_;
}
size_t Buffer::WritableBytes() const {
return buffer_.size() - writePos_;
}

size_t Buffer::prependableBytes() const {
return readPos_;
}

const char* Buffer::Peek() const {
return BeginPtr_() + readPos_;
}

char* Buffer::Peek(){
return BeginPtr_() + readPos_;
}

void Buffer::Retrieve(size_t len) {
assert(len <= ReadableBytes());
readPos_ += len;
}

void Buffer::RetrieveUntil(const char* end) {
assert(Peek() <= end );
Retrieve(end - Peek());
}

void Buffer::RetrieveAll() {
readPos_ = 0;
writePos_ = 0;
}

std::string Buffer::RetrieveAllToStr() {
std::string str(Peek(), ReadableBytes());
RetrieveAll();
return str;
}

const char* Buffer::BeginWriteConst() const {
return BeginPtr_() + writePos_;
}

char* Buffer::BeginWrite() {
return BeginPtr_() + writePos_;
}

void Buffer::HasWritten(size_t len) {
writePos_ += len;
}

void Buffer::Append(const std::string& str) {
Append(str.data(), str.length());
}
void Buffer::Append(const char* data, size_t len) {
EnsureWriteable(len);
std::copy(data, data + len, BeginWrite());
HasWritten(len);
}

void Buffer::Append(const void* data, size_t len) {
Append(static_cast<const char*>(data), len);
}

void Buffer::Append(const Buffer& buff) {
Append(buff.Peek(), buff.ReadableBytes());
}

void Buffer::EnsureWriteable(size_t len) {
if(WritableBytes() < len) {
MakeSpace_(len);
}
assert(WritableBytes() >= len);
}

ssize_t Buffer::ReadFd(int fd, int* saveErrno) {
char buff[MAX_BUFF_SIZE];
struct iovec iov[2];
const size_t writable = WritableBytes();
/* 分散读, 保证数据全部读完 */
iov[0].iov_base = BeginPtr_() + writePos_;
iov[0].iov_len = writable;
iov[1].iov_base = buff;
iov[1].iov_len = sizeof(buff);

const ssize_t len = readv(fd, iov, 2);
if(len < 0) {
*saveErrno = errno;
}
else if(static_cast<size_t>(len) <= writable) {
writePos_ += len;
}
else {
writePos_ = buffer_.size();
Append(buff, len - writePos_);
}
return len;
}

ssize_t Buffer::WriteFd(int fd, int* saveErrno) {
size_t readSize = ReadableBytes();
ssize_t len = write(fd, Peek(), readSize);
if(len < 0) {
*saveErrno = errno;
}
readPos_ += len;
return len;
}

char* Buffer::BeginPtr_() {
return &*buffer_.begin();
}

const char* Buffer::BeginPtr_() const {
return &*buffer_.begin();
}

void Buffer::MakeSpace_(size_t len) {
if(WritableBytes() + prependableBytes() < len) {
buffer_.resize(writePos_ + len);
}
else {
size_t readable = ReadableBytes();
std::copy(BeginPtr_() + readPos_, BeginPtr_() + writePos_, BeginPtr_());
readPos_ = 0;
writePos_ = readPos_ + readable;
assert(readable == ReadableBytes());
}
}
62 changes: 62 additions & 0 deletions code/buffer/buffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* @Author : mark
* @Date : 2020-06-26
* @copyleft GPL 2.0
*/

#ifndef BUFFER_H
#define BUFFER_H
#include <cstring> //perror
#include <iostream>
#include <unistd.h> // write
#include <sys/uio.h> //readv
#include <vector> //readv
#include <atomic>
#include <assert.h>


class Buffer {
public:
Buffer();
~Buffer() = default;

size_t WritableBytes() const;
size_t ReadableBytes() const ;
size_t prependableBytes() const;

const char* Peek() const;
char* Peek();
void EnsureWriteable(size_t len);
void HasWritten(size_t len);

void Retrieve(size_t len);
void RetrieveUntil(const char* end);

void RetrieveAll() ;
std::string RetrieveAllToStr();

const char* BeginWriteConst() const;
char* BeginWrite();

void Append(const std::string& str);
void Append(const char* data, size_t len);
void Append(const void* data, size_t len);
void Append(const Buffer& buff);

ssize_t ReadFd(int fd, int* Errno);
ssize_t WriteFd(int fd, int* Errno);

private:
const size_t MAX_BUFF_SIZE = 65536;
const size_t INIT_BUFF_SIZE = 1024;

char* BeginPtr_();
const char* BeginPtr_() const;
void MakeSpace_(size_t len);

std::vector<char> buffer_;
std::atomic<std::size_t> readPos_;
std::atomic<std::size_t> writePos_;
};

#endif //BUFFER_H

0 comments on commit e1bd71d

Please sign in to comment.