This class is for fast and small footprint buffering made specially for network I/O. It is similar to so-called circular buffers, but is not circular.
#ifndef _IO_BUFFER_H
#define _IO_BUFFER_H
#include <cstdint>
#include <cstring>
#include <cstdio>
namespace net{
template<size_t CAPACITY>
class IOBuffer{
public:
using size_type = uint16_t;
private:
size_type head_ = 0;
size_type tail_ = 0;
char buffer_[CAPACITY];
public:
void clear(){
head_ = 0;
tail_ = 0;
}
constexpr
static size_t max_size(){
return CAPACITY;
}
// ==================================
const char *data() const{
return & buffer_[head_];
}
char *dataTail(){
return & buffer_[tail_];
}
size_t size() const{
return tail_ - head_;
}
size_t capacity() const{
return CAPACITY - tail_;
}
// ==================================
bool push(const char *p){
return p ? push(strlen(p), p) : false;
}
bool push(size_t const len, const void *ptr = nullptr){
if (len == 0)
return false;
if (capacity() < len)
return false;
if (ptr)
memmove(&buffer_[tail_], ptr, len);
tail_ = (size_type) (tail_ + len);
return true;
}
bool pop(size_t const len){
if (len == 0)
return false;
auto const available = size();
if (available < len)
return false;
if (available == len){
clear();
return true;
}
head_ = (size_type) (head_ + len);
return true;
}
// ==================================
void print() const{
printf("h: %3u | t: %3u | ad: %3zu | ac: %3zu | %.*s\n",
head_, tail_,
size(), capacity(),
(int) size(), buffer_ );
}
};
} // namespace
#endif
Usual usage include several socket read()
until protocol data is collected, then several write()
until response is sent back.
Reads and writes will not be mixed, but for the moment this is responsibility of the caller.
print
is debug method, non intended to be called.
int main(){
using Buffer = net::IOBuffer<10>;
Buffer b;
b.print();
b.push("aaa");
b.print();
b.push("bbb");
b.print();
b.push("ccc");
b.print();
b.push("xxx");
b.print();
b.push("d");
b.print();
b.push("xxx");
b.print();
b.pop(3);
b.print();
b.pop(3);
b.print();
b.pop(b.size()); // same as b.clear()
b.print();
}