#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