Reputation: 2174
I'd like to be able to consume parts of a buffer until it's empty. I designed my own below, but I'd like to know if there is such thing in the std library already, so I remove the possibilities of implementing my own wrong.
Note that I use std::vector<T>
only for automatic storage. I don't do push_back
to insert and pop_back
to consume because I want the consumption of data to be as fast as possible.
#include <iostream>
#include <vector>
using namespace std;
template <class T>
class Buffer
{
public:
void write(T* buffer, size_t amountToWrite) {
if (amountToWrite <= this->_buffer.capacity()) {
std::copy(buffer, buffer + amountToWrite, this->_buffer.data());
_size += amountToWrite;
} else {
//In fact I wanted to increase capacity, not size. However we don't use the vector functions, so does it mater?
this->_buffer.resize(amountToWrite);
std::copy(buffer, buffer + amountToWrite, this->_buffer.data());
_size += amountToWrite;
}
}
size_t consume(T* bufferToWrite, size_t amountToConsume) {
if (_current==_size) {
//this means we've already read everything. Maybe we should throw or just return 0?
return 0;
}
if (amountToConsume <= this->_size) {
std::copy(this->_buffer.data() + _current, this->_buffer.data() + _current + amountToConsume, bufferToWrite);
_current += amountToConsume;
return amountToConsume;
} else {
size_t remaining = this->_size - amountToConsume;
std::copy(this->_buffer.data() + _current, this->_buffer.data() + _current + remaining, bufferToWrite);
_current += remaining;
return remaining;
}
}
private:
size_t _size = 0;
std::vector<T> _buffer;
size_t _current = 0;
};
int main()
{
Buffer<uint8_t> b;
uint8_t u[] = {1,2,3,4,5,6};
b.write(u, 6);
uint8_t r[3];
size_t consumedBytes = b.consume(r, 3);
std::cout << "consumed " << consumedBytes << std::endl;
for(int i=0; i<3; i++) {
std::cout << (int) r[i];
}
std::cout << std::endl;
size_t consumedBytes2 = b.consume(r, 3);
std::cout << "consumed " << consumedBytes2 << std::endl;
for(int i=0; i<3; i++) {
std::cout << (int) r[i];
}
std::cout << std::endl;
size_t consumedBytes3 = b.consume(r, 3);
std::cout << "consumed " << consumedBytes3 << std::endl;
return 0;
}
Do you see anything wrong in my implementation?
I'm trying to do the safest possible thing while making it fast.
Upvotes: 0
Views: 92
Reputation: 3941
I think you can take advantage of using dequeue from STL. It implements a doubly linkedlist in which you can read from one side and write from the other side of it. Check this link for more detail explanations.
Also the other best implementation for a buffer is a circular buffer implementation.
I leave a C++ implementation code for a circular buffer.
class MyCircularQueue {
vector<int> mem;
int front;
int rear;
int len;
int cnt;
public:
MyCircularQueue(int k) {
len = k;
mem = vector<int> (k);
front = 0;
rear = -1;
cnt=0;
}
bool enQueue(int value) {
if(isFull())
return false;
rear = (rear+1) %len;
mem[rear]= value;
cnt++;
return true;
}
bool deQueue() {
if (isEmpty())
return false;
front = (front+1) % len;
cnt--;
return true;
}
int Front() {
if (isEmpty())
return -1;
return mem[front];
}
int Rear() {
if (isEmpty())
return -1;
return mem[rear];
}
bool isEmpty() {
return (cnt ==0);
}
bool isFull() {
return ( cnt == len);
}
};
Upvotes: 1