Bogofilter adapter for OpenSMTPD in C++
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

132 lines
2.9 KiB

#include <vector>
#include <map>
#include <iterator>
template <class T>
class sparse_vector {
std::map<size_t, T> map;
size_t _size = 0;
public:
const T empty;
template <class U>
class iterator : public std::iterator<std::input_iterator_tag, U> {
sparse_vector<U> & vector;
size_t index;
public:
iterator(sparse_vector<U> & vector, size_t index) : vector(vector), index(index) {}
iterator(const iterator<U> & from) : vector(from.vector), index(from.index) {}
// Prefix increment operator
iterator<U> & operator++() {
++index;
return *this;
}
// Postfix increment operator
iterator<U> operator++(int) {
iterator<U> tmp(*this);
operator++();
return tmp;
}
bool operator==(const iterator<U> & rhs) const {
return index == rhs.index;
}
bool operator!=(const iterator<U> & rhs) const {
return index != rhs.index;
}
U & operator*() const {
return vector.at(index);
}
};
sparse_vector() {}
// Construct from element list given as arguments
sparse_vector(std::initializer_list<T> list) {
size_t index = 0;
for(auto element : list) {
map[index] = element;
}
}
// Copy constructor
sparse_vector(const sparse_vector<T> & svector) {
map = svector.map;
_size = svector._size;
}
// Move constructor
sparse_vector(sparse_vector<T> && svector) {
map = std::move(svector.map);
_size = svector._size;
svector._size = 0;
}
// Construct from regular vector
sparse_vector(const std::vector<T> vector) {
for(size_t index = 0; index < vector.size(); ++index) {
map[index] = vector.at(index);
}
_size = vector.size();
}
// Move assignment operator
sparse_vector<T> & operator=(sparse_vector<T> && svector) {
map = std::move(svector.map);
size = svector._size;
svector._size = 0;
return *this;
}
size_t size() const {
return _size;
}
const T & at(size_t index) const {
return map.at(index);
}
bool has(size_t index) const {
return map.count(index) == 1;
}
void push_back(const T & element) {
map[_size++] = element;
}
template <class Range>
void push_back(Range range) {
for(T & element : range) {
push_back(element);
}
}
T pop_back() {
--_size;
if(has(_size)) {
T element = map->at(_size);
map.erase(_size);
return element;
}
return empty;
}
iterator<T> begin() const {
return iterator<T>(*this, 0);
}
iterator<T> end() const {
return iterator<T>(*this, size());
}
T & operator[](size_t index) {
return map[index];
}
};