2017-04-04 18:00:17 -04:00
|
|
|
#ifndef UTIL_VECTOR_VIEW_HPP
|
|
|
|
#define UTIL_VECTOR_VIEW_HPP
|
2013-09-17 08:23:06 -04:00
|
|
|
|
2017-04-01 21:00:03 -04:00
|
|
|
#include "util/exception.hpp"
|
2017-04-01 21:25:55 -04:00
|
|
|
#include "util/log.hpp"
|
2016-05-23 20:13:32 -04:00
|
|
|
|
2017-04-04 03:52:00 -04:00
|
|
|
#include "storage/shared_memory_ownership.hpp"
|
2017-03-29 08:06:52 -04:00
|
|
|
|
2017-01-18 14:40:38 -05:00
|
|
|
#include <boost/assert.hpp>
|
|
|
|
#include <boost/iterator/iterator_facade.hpp>
|
|
|
|
#include <boost/iterator/reverse_iterator.hpp>
|
|
|
|
|
|
|
|
#include <climits>
|
2016-02-05 10:45:36 -05:00
|
|
|
#include <cstddef>
|
|
|
|
|
2013-09-23 12:01:30 -04:00
|
|
|
#include <algorithm>
|
2013-09-17 08:23:06 -04:00
|
|
|
#include <iterator>
|
2014-05-07 12:39:16 -04:00
|
|
|
#include <type_traits>
|
2016-02-05 10:45:36 -05:00
|
|
|
#include <utility>
|
2016-05-27 15:05:04 -04:00
|
|
|
#include <vector>
|
2013-09-17 08:23:06 -04:00
|
|
|
|
2017-07-07 06:09:52 -04:00
|
|
|
#if USE_STXXL_LIBRARY
|
|
|
|
#include <stxxl/vector>
|
|
|
|
#endif
|
|
|
|
|
2016-01-05 10:51:13 -05:00
|
|
|
namespace osrm
|
|
|
|
{
|
|
|
|
namespace util
|
|
|
|
{
|
|
|
|
|
2017-01-18 14:40:38 -05:00
|
|
|
template <typename DataT>
|
2017-04-04 18:00:17 -04:00
|
|
|
class VectorViewIterator : public boost::iterator_facade<VectorViewIterator<DataT>,
|
|
|
|
DataT,
|
|
|
|
boost::random_access_traversal_tag>
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
2017-04-04 19:01:00 -04:00
|
|
|
typedef boost::iterator_facade<VectorViewIterator<DataT>,
|
|
|
|
DataT,
|
|
|
|
boost::random_access_traversal_tag>
|
|
|
|
base_t;
|
2014-05-07 12:39:16 -04:00
|
|
|
|
|
|
|
public:
|
2017-01-18 14:40:38 -05:00
|
|
|
typedef typename base_t::value_type value_type;
|
|
|
|
typedef typename base_t::difference_type difference_type;
|
|
|
|
typedef typename base_t::reference reference;
|
|
|
|
typedef std::random_access_iterator_tag iterator_category;
|
2013-09-17 08:23:06 -04:00
|
|
|
|
2017-04-04 18:00:17 -04:00
|
|
|
explicit VectorViewIterator() : m_value(nullptr) {}
|
|
|
|
explicit VectorViewIterator(DataT *x) : m_value(x) {}
|
2016-07-22 12:23:54 -04:00
|
|
|
|
2017-01-18 14:40:38 -05:00
|
|
|
private:
|
|
|
|
void increment() { ++m_value; }
|
|
|
|
void decrement() { --m_value; }
|
|
|
|
void advance(difference_type offset) { m_value += offset; }
|
2017-04-04 18:00:17 -04:00
|
|
|
bool equal(const VectorViewIterator &other) const { return m_value == other.m_value; }
|
2017-01-18 14:40:38 -05:00
|
|
|
reference dereference() const { return *m_value; }
|
2017-04-04 18:00:17 -04:00
|
|
|
difference_type distance_to(const VectorViewIterator &other) const
|
2016-07-22 12:23:54 -04:00
|
|
|
{
|
2017-01-18 14:40:38 -05:00
|
|
|
return other.m_value - m_value;
|
2016-07-22 12:23:54 -04:00
|
|
|
}
|
2017-01-18 14:40:38 -05:00
|
|
|
|
|
|
|
friend class ::boost::iterator_core_access;
|
|
|
|
DataT *m_value;
|
2016-07-22 12:23:54 -04:00
|
|
|
};
|
|
|
|
|
2017-04-03 03:49:47 -04:00
|
|
|
template <typename DataT> class vector_view
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
|
|
|
private:
|
|
|
|
DataT *m_ptr;
|
2013-09-17 08:23:06 -04:00
|
|
|
std::size_t m_size;
|
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
public:
|
2017-02-23 10:39:29 -05:00
|
|
|
using value_type = DataT;
|
2017-04-04 18:00:17 -04:00
|
|
|
using iterator = VectorViewIterator<DataT>;
|
|
|
|
using const_iterator = VectorViewIterator<const DataT>;
|
2017-01-18 14:40:38 -05:00
|
|
|
using reverse_iterator = boost::reverse_iterator<iterator>;
|
|
|
|
|
2017-04-03 03:49:47 -04:00
|
|
|
vector_view() : m_ptr(nullptr), m_size(0) {}
|
2013-09-23 12:01:30 -04:00
|
|
|
|
2017-04-03 03:49:47 -04:00
|
|
|
vector_view(DataT *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
|
2013-09-17 08:23:06 -04:00
|
|
|
|
2016-05-01 07:48:56 -04:00
|
|
|
void reset(DataT *ptr, std::size_t size)
|
|
|
|
{
|
|
|
|
m_ptr = ptr;
|
|
|
|
m_size = size;
|
|
|
|
}
|
|
|
|
|
2017-02-23 10:39:29 -05:00
|
|
|
void reset(void *ptr, std::size_t size)
|
|
|
|
{
|
|
|
|
m_ptr = reinterpret_cast<DataT *>(ptr);
|
|
|
|
m_size = size;
|
|
|
|
}
|
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
DataT &at(const std::size_t index) { return m_ptr[index]; }
|
2013-09-23 12:01:30 -04:00
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
const DataT &at(const std::size_t index) const { return m_ptr[index]; }
|
2013-09-23 07:30:21 -04:00
|
|
|
|
2017-01-18 14:40:38 -05:00
|
|
|
auto begin() const { return iterator(m_ptr); }
|
2013-09-23 12:01:30 -04:00
|
|
|
|
2017-01-18 14:40:38 -05:00
|
|
|
auto end() const { return iterator(m_ptr + m_size); }
|
2013-09-17 08:23:06 -04:00
|
|
|
|
2017-03-08 19:41:18 -05:00
|
|
|
auto cbegin() const { return const_iterator(m_ptr); }
|
|
|
|
|
|
|
|
auto cend() const { return const_iterator(m_ptr + m_size); }
|
|
|
|
|
2017-01-18 14:40:38 -05:00
|
|
|
auto rbegin() const { return reverse_iterator(iterator(m_ptr + m_size)); }
|
2016-07-22 12:23:54 -04:00
|
|
|
|
2017-01-18 14:40:38 -05:00
|
|
|
auto rend() const { return reverse_iterator(iterator(m_ptr)); }
|
2016-07-22 12:23:54 -04:00
|
|
|
|
2013-09-17 08:23:06 -04:00
|
|
|
std::size_t size() const { return m_size; }
|
|
|
|
|
2018-03-22 14:26:40 -04:00
|
|
|
void resize(const size_t size)
|
|
|
|
{
|
2018-03-16 10:59:05 -04:00
|
|
|
if (size > m_size)
|
|
|
|
{
|
|
|
|
throw util::exception("Trying to resize a view to a larger size.");
|
|
|
|
}
|
|
|
|
m_size = size;
|
|
|
|
}
|
|
|
|
|
2014-02-21 10:55:41 -05:00
|
|
|
bool empty() const { return 0 == size(); }
|
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
DataT &operator[](const unsigned index)
|
|
|
|
{
|
2013-09-17 08:23:06 -04:00
|
|
|
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
|
|
|
return m_ptr[index];
|
|
|
|
}
|
2013-09-23 12:01:30 -04:00
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
const DataT &operator[](const unsigned index) const
|
|
|
|
{
|
2013-09-23 12:01:30 -04:00
|
|
|
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
|
|
|
return m_ptr[index];
|
|
|
|
}
|
2016-02-05 11:53:17 -05:00
|
|
|
|
2017-03-07 08:14:10 -05:00
|
|
|
const DataT &front() const
|
|
|
|
{
|
2017-03-06 17:00:11 -05:00
|
|
|
BOOST_ASSERT_MSG(m_size > 0, "invalid size");
|
|
|
|
return m_ptr[0];
|
|
|
|
}
|
|
|
|
|
2017-03-07 08:14:10 -05:00
|
|
|
const DataT &back() const
|
|
|
|
{
|
2017-03-06 17:00:11 -05:00
|
|
|
BOOST_ASSERT_MSG(m_size > 0, "invalid size");
|
|
|
|
return m_ptr[m_size - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
auto data() const { return m_ptr; }
|
|
|
|
|
2017-04-01 21:25:55 -04:00
|
|
|
template <typename T> friend void swap(vector_view<T> &, vector_view<T> &) noexcept;
|
2013-09-17 08:23:06 -04:00
|
|
|
};
|
|
|
|
|
2017-04-03 03:49:47 -04:00
|
|
|
template <> class vector_view<bool>
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
|
|
|
private:
|
|
|
|
unsigned *m_ptr;
|
2014-04-11 14:03:09 -04:00
|
|
|
std::size_t m_size;
|
|
|
|
|
2017-06-15 10:52:14 -04:00
|
|
|
static constexpr std::size_t UNSIGNED_BITS = CHAR_BIT * sizeof(unsigned);
|
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
public:
|
2017-04-01 21:00:03 -04:00
|
|
|
using value_type = bool;
|
2017-06-15 10:52:14 -04:00
|
|
|
struct reference
|
|
|
|
{
|
|
|
|
reference &operator=(bool value)
|
|
|
|
{
|
|
|
|
*m_ptr = (*m_ptr & ~mask) | (static_cast<unsigned>(value) * mask);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
operator bool() const { return (*m_ptr) & mask; }
|
|
|
|
|
|
|
|
bool operator==(const reference &other) const
|
|
|
|
{
|
|
|
|
return other.m_ptr == m_ptr && other.mask == mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
friend std::ostream &operator<<(std::ostream &os, const reference &rhs)
|
|
|
|
{
|
|
|
|
return os << static_cast<bool>(rhs);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned *m_ptr;
|
|
|
|
const unsigned mask;
|
|
|
|
};
|
2017-04-01 21:00:03 -04:00
|
|
|
|
2017-04-03 03:49:47 -04:00
|
|
|
vector_view() : m_ptr(nullptr), m_size(0) {}
|
2014-04-11 14:03:09 -04:00
|
|
|
|
2017-04-03 03:49:47 -04:00
|
|
|
vector_view(unsigned *ptr, std::size_t size) : m_ptr(ptr), m_size(size) {}
|
2014-04-11 14:03:09 -04:00
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
bool at(const std::size_t index) const
|
|
|
|
{
|
2017-01-18 14:40:38 -05:00
|
|
|
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
2017-06-15 10:52:14 -04:00
|
|
|
const std::size_t bucket = index / UNSIGNED_BITS;
|
|
|
|
const unsigned offset = index % UNSIGNED_BITS;
|
2016-02-05 11:54:59 -05:00
|
|
|
return m_ptr[bucket] & (1u << offset);
|
2014-04-11 14:03:09 -04:00
|
|
|
}
|
|
|
|
|
2018-03-22 14:26:40 -04:00
|
|
|
void reset(unsigned *ptr, std::size_t size)
|
|
|
|
{
|
2018-03-16 10:59:05 -04:00
|
|
|
m_ptr = ptr;
|
|
|
|
m_size = size;
|
|
|
|
}
|
|
|
|
|
2018-03-22 14:26:40 -04:00
|
|
|
void resize(const size_t size)
|
|
|
|
{
|
2018-03-16 10:59:05 -04:00
|
|
|
if (size > m_size)
|
|
|
|
{
|
|
|
|
throw util::exception("Trying to resize a view to a larger size.");
|
|
|
|
}
|
|
|
|
m_size = size;
|
|
|
|
}
|
2016-05-01 07:48:56 -04:00
|
|
|
|
2014-04-11 14:03:09 -04:00
|
|
|
std::size_t size() const { return m_size; }
|
|
|
|
|
|
|
|
bool empty() const { return 0 == size(); }
|
|
|
|
|
2017-01-18 14:40:38 -05:00
|
|
|
bool operator[](const unsigned index) const { return at(index); }
|
2016-02-05 11:53:17 -05:00
|
|
|
|
2017-06-15 10:52:14 -04:00
|
|
|
reference operator[](const unsigned index)
|
|
|
|
{
|
|
|
|
BOOST_ASSERT(index < m_size);
|
|
|
|
const std::size_t bucket = index / UNSIGNED_BITS;
|
|
|
|
const unsigned offset = index % UNSIGNED_BITS;
|
|
|
|
return reference{m_ptr + bucket, 1u << offset};
|
|
|
|
}
|
|
|
|
|
2017-04-03 04:28:46 -04:00
|
|
|
template <typename T> friend void swap(vector_view<T> &, vector_view<T> &) noexcept;
|
2014-04-11 14:03:09 -04:00
|
|
|
};
|
|
|
|
|
2017-04-03 03:49:47 -04:00
|
|
|
// Both vector_view<T> and the vector_view<bool> specializations share this impl.
|
2017-04-03 04:28:46 -04:00
|
|
|
template <typename DataT> void swap(vector_view<DataT> &lhs, vector_view<DataT> &rhs) noexcept
|
2016-02-05 11:53:17 -05:00
|
|
|
{
|
|
|
|
std::swap(lhs.m_ptr, rhs.m_ptr);
|
|
|
|
std::swap(lhs.m_size, rhs.m_size);
|
|
|
|
}
|
|
|
|
|
2017-07-07 06:09:52 -04:00
|
|
|
#if USE_STXXL_LIBRARY
|
|
|
|
template <typename T> using ExternalVector = stxxl::vector<T>;
|
|
|
|
#else
|
|
|
|
template <typename T> using ExternalVector = std::vector<T>;
|
|
|
|
#endif
|
|
|
|
|
2017-04-09 09:59:55 -04:00
|
|
|
template <typename DataT, storage::Ownership Ownership>
|
2017-04-10 04:35:52 -04:00
|
|
|
using InternalOrExternalVector =
|
|
|
|
typename std::conditional<Ownership == storage::Ownership::External,
|
2017-07-07 06:09:52 -04:00
|
|
|
ExternalVector<DataT>,
|
2017-04-10 04:35:52 -04:00
|
|
|
std::vector<DataT>>::type;
|
2017-04-09 09:59:55 -04:00
|
|
|
|
2017-04-04 18:00:17 -04:00
|
|
|
template <typename DataT, storage::Ownership Ownership>
|
|
|
|
using ViewOrVector = typename std::conditional<Ownership == storage::Ownership::View,
|
|
|
|
vector_view<DataT>,
|
2017-04-09 09:59:55 -04:00
|
|
|
InternalOrExternalVector<DataT, Ownership>>::type;
|
2017-06-15 10:52:14 -04:00
|
|
|
|
|
|
|
// We can use this for compile time assertions
|
|
|
|
template <typename ValueT, typename VectorT>
|
|
|
|
struct is_view_or_vector
|
|
|
|
: std::integral_constant<bool,
|
|
|
|
std::is_same<std::vector<ValueT>, VectorT>::value ||
|
|
|
|
std::is_same<util::vector_view<ValueT>, VectorT>::value>
|
|
|
|
{
|
|
|
|
};
|
2016-01-05 10:51:13 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-28 06:13:18 -05:00
|
|
|
#endif // SHARED_MEMORY_VECTOR_WRAPPER_HPP
|