344 lines
7.4 KiB
C++
344 lines
7.4 KiB
C++
|
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||
|
|
||
|
/*!
|
||
|
*
|
||
|
* \file svector.hpp
|
||
|
* \ingroup aux_classes
|
||
|
*
|
||
|
* \brief Simple yet efficient dynamic vector
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
/* ***************************************************************************
|
||
|
*
|
||
|
* FastFlow is free software; you can redistribute it and/or modify it
|
||
|
* under the terms of the GNU Lesser General Public License version 3 as
|
||
|
* published by the Free Software Foundation.
|
||
|
* Starting from version 3.0.1 FastFlow is dual licensed under the GNU LGPLv3
|
||
|
* or MIT License (https://github.com/ParaGroup/WindFlow/blob/vers3.x/LICENSE.MIT)
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||
|
* License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU Lesser General Public License
|
||
|
* along with this program; if not, write to the Free Software Foundation,
|
||
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||
|
*
|
||
|
****************************************************************************
|
||
|
*/
|
||
|
#ifndef FF_SVECTOR_HPP
|
||
|
#define FF_SVECTOR_HPP
|
||
|
|
||
|
/* Simple yet efficient dynamic vector */
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <new>
|
||
|
|
||
|
// to disable the warning related to the use of realloc for non trivially copyable types
|
||
|
#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 800)
|
||
|
#pragma GCC diagnostic push
|
||
|
#pragma GCC diagnostic ignored "-Wclass-memaccess"
|
||
|
#endif
|
||
|
|
||
|
namespace ff {
|
||
|
|
||
|
/*!
|
||
|
* \ingroup aux_classes
|
||
|
*
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/*!
|
||
|
* \class svector
|
||
|
* \ingroup aux_classes
|
||
|
*
|
||
|
* \brief Simple yet efficient dynamic vector
|
||
|
*
|
||
|
* This class is defined in \ref svector.hpp
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
template <typename T>
|
||
|
class svector {
|
||
|
enum {SVECTOR_CHUNK=512};
|
||
|
public:
|
||
|
typedef T* iterator;
|
||
|
typedef const T* const_iterator;
|
||
|
typedef T vector_type;
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* @param chunk is the allocation chunk
|
||
|
*/
|
||
|
svector(size_t chunk=SVECTOR_CHUNK):first(NULL),len(0),cap(0),chunk(chunk?chunk:1) {
|
||
|
reserve(chunk);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Constructor
|
||
|
*
|
||
|
*/
|
||
|
svector(const svector & v):first(NULL),len(0),cap(0),chunk(v.chunk) {
|
||
|
if(v.len) {
|
||
|
const_iterator i1=v.begin();
|
||
|
const_iterator i2=v.end();
|
||
|
first=(vector_type*)::malloc((i2-i1)*sizeof(vector_type));
|
||
|
while(i1!=i2) push_back(*(i1++));
|
||
|
return;
|
||
|
}
|
||
|
reserve(v.chunk);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Constructor
|
||
|
*
|
||
|
*/
|
||
|
svector(const_iterator i1,const_iterator i2):first(0),len(0),cap(0),chunk(SVECTOR_CHUNK) {
|
||
|
first=(vector_type*)::malloc((i2-i1)*sizeof(vector_type));
|
||
|
while(i1!=i2) push_back(*(i1++));
|
||
|
}
|
||
|
|
||
|
// TODO: implement swap and re-implement move constructor and move operator with swap
|
||
|
|
||
|
/**
|
||
|
* Move constructor
|
||
|
*/
|
||
|
svector(svector &&v) {
|
||
|
first = v.first;
|
||
|
len = v.len;
|
||
|
cap = v.cap;
|
||
|
chunk = v.chunk;
|
||
|
|
||
|
v.first = nullptr;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Destructor
|
||
|
*/
|
||
|
~svector() {
|
||
|
if(first) {
|
||
|
clear();
|
||
|
::free(first);
|
||
|
first=NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Copy
|
||
|
*/
|
||
|
svector& operator=(const svector & v) {
|
||
|
if (this != &v) {
|
||
|
clear();
|
||
|
const_iterator i1=v.begin();
|
||
|
const_iterator i2=v.end();
|
||
|
while(i1!=i2) push_back(*(i1++));
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
svector& operator=(svector && v) {
|
||
|
if (this != &v) {
|
||
|
if (first) { clear(); ::free(first); }
|
||
|
first=v.first;
|
||
|
len =v.len;
|
||
|
cap =v.cap;
|
||
|
chunk=v.chunk;
|
||
|
|
||
|
v.first = nullptr;
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Merge
|
||
|
*/
|
||
|
svector& operator+=(const svector & v) {
|
||
|
const_iterator i1=v.begin();
|
||
|
const_iterator i2=v.end();
|
||
|
while(i1!=i2) push_back(*(i1++));
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reserve
|
||
|
*/
|
||
|
inline void reserve(size_t newcapacity) {
|
||
|
if(newcapacity<=cap) return;
|
||
|
if (first==NULL)
|
||
|
first=(vector_type*)::malloc(sizeof(vector_type)*newcapacity);
|
||
|
else
|
||
|
first=(vector_type*)::realloc(first,sizeof(vector_type)*newcapacity);
|
||
|
cap = newcapacity;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Resize
|
||
|
*/
|
||
|
inline void resize(size_t newsize) {
|
||
|
if (len >= newsize) {
|
||
|
while(len>newsize) pop_back();
|
||
|
return;
|
||
|
}
|
||
|
reserve(newsize);
|
||
|
while(len<newsize)
|
||
|
new (first + len++) vector_type();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* push_back
|
||
|
*/
|
||
|
inline void push_back(const vector_type & elem) {
|
||
|
if (len==cap) reserve(cap+chunk);
|
||
|
new (first + len++) vector_type(elem);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* pop_back
|
||
|
*/
|
||
|
inline void pop_back() {
|
||
|
(first + --len)->~vector_type();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* back
|
||
|
*/
|
||
|
inline vector_type& back() const {
|
||
|
return first[len-1];
|
||
|
//return *(vector_type *)0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* front
|
||
|
*/
|
||
|
inline vector_type& front() {
|
||
|
return first[0];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* front
|
||
|
*/
|
||
|
inline const vector_type& front() const {
|
||
|
return first[0];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* erease
|
||
|
*/
|
||
|
inline iterator erase(iterator where) {
|
||
|
iterator i1=begin();
|
||
|
iterator i2=end();
|
||
|
while(i1!=i2) {
|
||
|
if (i1==where) { --len; break;}
|
||
|
else i1++;
|
||
|
}
|
||
|
|
||
|
for(iterator i3=i1++; i1!=i2; ++i3, ++i1)
|
||
|
*i3 = *i1;
|
||
|
|
||
|
return begin();
|
||
|
}
|
||
|
/**
|
||
|
* insert
|
||
|
*/
|
||
|
inline iterator insert(iterator where, const vector_type & elem) {
|
||
|
iterator i1=begin();
|
||
|
iterator i2=end();
|
||
|
if (where == i2) {
|
||
|
push_back(elem);
|
||
|
return end();
|
||
|
}
|
||
|
while(i1!=i2) {
|
||
|
if (i1==where) {
|
||
|
++len;
|
||
|
if (len==cap) reserve(cap+chunk);
|
||
|
break;
|
||
|
}
|
||
|
else i1++;
|
||
|
}
|
||
|
for(iterator i3=i2+1; i2>=i1; --i2, --i3)
|
||
|
*i3 = *i2;
|
||
|
size_t pos=(i1-begin());
|
||
|
new (first + pos) vector_type(elem);
|
||
|
return begin()+pos;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* size
|
||
|
*/
|
||
|
inline size_t size() const { return len; }
|
||
|
|
||
|
/**
|
||
|
* empty
|
||
|
*/
|
||
|
inline bool empty() const { return (len==0);}
|
||
|
|
||
|
/**
|
||
|
* capacity
|
||
|
*/
|
||
|
inline size_t capacity() const { return cap;}
|
||
|
|
||
|
/**
|
||
|
* clear
|
||
|
*/
|
||
|
inline void clear() { while(size()>0) pop_back(); }
|
||
|
|
||
|
/**
|
||
|
* begin
|
||
|
*/
|
||
|
iterator begin() { return first; }
|
||
|
|
||
|
/**
|
||
|
* end
|
||
|
*/
|
||
|
iterator end() { return first+len; }
|
||
|
|
||
|
/**
|
||
|
* begin
|
||
|
*/
|
||
|
const_iterator begin() const { return first; }
|
||
|
|
||
|
/**
|
||
|
* end
|
||
|
*/
|
||
|
const_iterator end() const { return first+len; }
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Access element
|
||
|
*/
|
||
|
vector_type& operator[](size_t n) {
|
||
|
reserve(n+1);
|
||
|
return first[n];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Access element
|
||
|
*/
|
||
|
const vector_type& operator[](size_t n) const { return first[n]; }
|
||
|
|
||
|
private:
|
||
|
vector_type* first;
|
||
|
size_t len;
|
||
|
size_t cap;
|
||
|
size_t chunk;
|
||
|
};
|
||
|
|
||
|
/*!
|
||
|
* @}
|
||
|
* \endlink
|
||
|
*/
|
||
|
|
||
|
} // namespace ff
|
||
|
|
||
|
#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 800)
|
||
|
#pragma GCC diagnostic pop
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
#endif /* FF_SVECTOR_HPP */
|