209 lines
3.9 KiB
C++
209 lines
3.9 KiB
C++
|
|
|
|
|
|
#ifndef headerfile_picotools_membuffer_membuffer
|
|
#define headerfile_picotools_membuffer_membuffer
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
namespace PT
|
|
{
|
|
|
|
|
|
template<class ItemType, size_t stack_size>
|
|
class MemBuffer
|
|
{
|
|
public:
|
|
|
|
class Iterator
|
|
{
|
|
size_t vector_index;
|
|
size_t array_index;
|
|
|
|
bool operator==(const Iterator & i);
|
|
bool operator!=(const Iterator & i);
|
|
bool operator<(const Iterator & i);
|
|
|
|
Iterator & operator++(); // prefix ++
|
|
Iterator operator++(int); // postfix ++
|
|
|
|
ItemType & operator*();
|
|
|
|
};
|
|
|
|
class ConstIterator
|
|
{
|
|
|
|
|
|
};
|
|
|
|
MemBuffer();
|
|
|
|
void Append(ItemType item);
|
|
void Append(ItemType * item_array, size_t len);
|
|
void Size() const;
|
|
void Empty() const;
|
|
|
|
void Reserve();
|
|
void Capacity();
|
|
void SetMinCapacity();
|
|
void Clear(); // frees memory but only to SetMinCapacity()
|
|
|
|
Iterator Begin();
|
|
ConstIterator Begin() const;
|
|
|
|
Iterator End();
|
|
ConstIterator End() const;
|
|
|
|
// may it's a better to have a static size of dynamic_array items
|
|
// so we can have following operators working in O(1)
|
|
//ItemType & operator[](size_t i);
|
|
//const ItemType operator[](size_t i) const;
|
|
|
|
private:
|
|
|
|
struct MemArray
|
|
{
|
|
size_t size;
|
|
size_t size_used;
|
|
ItemType * buf;
|
|
};
|
|
|
|
ItemType stack_array[stack_size];
|
|
std::vector<MemArray> dynamic_array;
|
|
size_t size_used; // the size of all items
|
|
size_t reserve_size; // how many memory is reserved
|
|
size_t last_allocated_list; // size of the last allocated vector
|
|
};
|
|
|
|
|
|
|
|
|
|
template<class ItemType, size_t stack_size>
|
|
MemBuffer<ItemType>::Iterator & MemBuffer<ItemType>::Iterator::operator++()
|
|
{
|
|
if( vector_index == size_t(-1) )
|
|
{
|
|
array_index += 1;
|
|
|
|
if( array_index >= stack_size )
|
|
{
|
|
array_index = 0;
|
|
vector_index = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// if not it means that this iterator is pointing at End()
|
|
if( vector_index < dynamic_array.size() && array_index < dynamic_array.back().size_used )
|
|
{
|
|
array_index += 1;
|
|
|
|
if( array_index >= dynamic_array.back().size )
|
|
{
|
|
array_index = 0;
|
|
vector_index += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
template<class ItemType, size_t stack_size>
|
|
MemBuffer<ItemType>::Iterator MemBuffer<ItemType>::Iterator::operator++(int)
|
|
{
|
|
Iterator old(*this);
|
|
operator++();
|
|
|
|
return old;
|
|
}
|
|
|
|
|
|
|
|
template<class ItemType, size_t stack_size>
|
|
void MemBuffer<ItemType>::MemBuffer()
|
|
{
|
|
size_used = 0;
|
|
list_size = 0;
|
|
reserve_size = stack_size;
|
|
last_allocated_list = 512; // minimum 1
|
|
}
|
|
|
|
|
|
template<class ItemType, size_t stack_size>
|
|
void MemBuffer<ItemType>::Append(ItemType item)
|
|
{
|
|
if( size_used < stack_size )
|
|
{
|
|
stack_array[size_used];
|
|
}
|
|
else
|
|
{
|
|
if( dynamic_array.empty() || dynamic_array.back().size_used >= dynamic_array.back().size )
|
|
{
|
|
last_allocated_list = last_allocated_list * 2;
|
|
dynamic_array.push_back(MemArray());
|
|
dynamic_array.back().size = last_allocated_list;
|
|
dynamic_array.back().size_used = 0;
|
|
dynamic_array.back().buf = new ItemType[last_allocated_list];
|
|
reserve_size += last_allocated_list;
|
|
}
|
|
|
|
dynamic_array.back().buf[dynamic_array.back().size_used] = item;
|
|
dynamic_array.back().size_used += 1;
|
|
}
|
|
|
|
size_used += 1;
|
|
}
|
|
|
|
|
|
template<class ItemType, size_t stack_size>
|
|
void MemBuffer<ItemType>::Append(ItemType * item_array, size_t len)
|
|
{
|
|
// in the future we can add a test
|
|
// if the array can be placed directly in the last item from std::list
|
|
// the we put it all
|
|
|
|
if( size_used < stack_size && size_used + len <= stack_size )
|
|
{
|
|
// may memcpy in the future? need some tests
|
|
|
|
for(size_t i=0 ; i<len ; ++i)
|
|
stack_array[size_used++] = item_array[i];
|
|
|
|
return;
|
|
}
|
|
|
|
if( !dynamic_array.empty() && dynamic_array.back().size_used + len <= dynamic_array.back().size )
|
|
{
|
|
ItemType * buf = dynamic_array.back().buf;
|
|
size_t bufsize = dynamic_array.back().size_used;
|
|
|
|
for(size_t i=0 ; i<len ; ++i)
|
|
buf[bufsize++] = item_array[i];
|
|
|
|
dynamic_array.back().size_used += len;
|
|
size_used += len;
|
|
|
|
return;
|
|
}
|
|
|
|
for(size_t i=0 ; i<len ; ++i)
|
|
Append(item_array[i]);
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
#endif
|
|
|