diff --git a/membuffer/membuffer.h b/membuffer/membuffer.h new file mode 100644 index 0000000..710c160 --- /dev/null +++ b/membuffer/membuffer.h @@ -0,0 +1,208 @@ + + + +#ifndef headerfile_picotools_membuffer_membuffer +#define headerfile_picotools_membuffer_membuffer + + +#include + + + + +namespace PT +{ + + +template +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 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 +MemBuffer::Iterator & MemBuffer::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 +MemBuffer::Iterator MemBuffer::Iterator::operator++(int) +{ + Iterator old(*this); + operator++(); + +return old; +} + + + +template +void MemBuffer::MemBuffer() +{ + size_used = 0; + list_size = 0; + reserve_size = stack_size; + last_allocated_list = 512; // minimum 1 +} + + +template +void MemBuffer::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 +void MemBuffer::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