Program Listing for File ResourceLimitedVector.hpp
↰ Return to documentation for file (/tmp/ws/src/fastrtps/include/fastrtps/utils/collections/ResourceLimitedVector.hpp
)
// Copyright 2019 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef FASTRTPS_UTILS_COLLECTIONS_RESOURCELIMITEDVECTOR_HPP_
#define FASTRTPS_UTILS_COLLECTIONS_RESOURCELIMITEDVECTOR_HPP_
#include "ResourceLimitedContainerConfig.hpp"
#include <assert.h>
#include <algorithm>
#include <type_traits>
#include <vector>
namespace eprosima {
namespace fastrtps {
template <
typename _Ty,
typename _KeepOrderEnabler = std::false_type,
typename _LimitsConfig = ResourceLimitedContainerConfig,
typename _Alloc = std::allocator<_Ty>,
typename _Collection = std::vector<_Ty, _Alloc>>
class ResourceLimitedVector
{
public:
using configuration_type = _LimitsConfig;
using collection_type = _Collection;
using value_type = _Ty;
using allocator_type = _Alloc;
using pointer = typename collection_type::pointer;
using const_pointer = typename collection_type::const_pointer;
using reference = typename collection_type::reference;
using const_reference = typename collection_type::const_reference;
using size_type = typename collection_type::size_type;
using difference_type = typename collection_type::difference_type;
using iterator = typename collection_type::iterator;
using const_iterator = typename collection_type::const_iterator;
using reverse_iterator = typename collection_type::reverse_iterator;
using const_reverse_iterator = typename collection_type::const_reverse_iterator;
ResourceLimitedVector(
configuration_type cfg = configuration_type(),
const allocator_type& alloc = allocator_type())
: configuration_(cfg)
, collection_(alloc)
{
collection_.reserve(cfg.initial);
}
ResourceLimitedVector(
const ResourceLimitedVector& other)
: configuration_(other.configuration_)
, collection_(other.collection_.get_allocator())
{
collection_.reserve(other.collection_.capacity());
collection_.assign(other.collection_.begin(), other.collection_.end());
}
virtual ~ResourceLimitedVector () = default;
ResourceLimitedVector& operator = (
const ResourceLimitedVector& other)
{
clear();
for (const_reference item : other)
{
push_back(item);
}
assert(size() == other.size());
return *this;
}
iterator insert(
const_iterator pos,
const value_type& value)
{
auto dist = std::distance(collection_.cbegin(), pos);
if (!ensure_capacity())
{
return end();
}
return collection_.insert(collection_.cbegin() + dist, value);
}
iterator insert(
const_iterator pos,
value_type&& value)
{
auto dist = std::distance(collection_.cbegin(), pos);
if (!ensure_capacity())
{
return end();
}
return collection_.insert(collection_.cbegin() + dist, std::move(value));
}
pointer push_back(
const value_type& val)
{
return emplace_back(val);
}
pointer push_back(
value_type&& val)
{
if (!ensure_capacity())
{
// Indicate error by returning null pointer
return nullptr;
}
// Move the element at the end of the collection
collection_.push_back(std::move(val));
// Return pointer to newly created element
return &collection_.back();
}
template<typename ... Args>
pointer emplace_back(
Args&& ... args)
{
if (!ensure_capacity())
{
// Indicate error by returning null pointer
return nullptr;
}
// Construct new element at the end of the collection
collection_.emplace_back(args ...);
// Return pointer to newly created element
return &collection_.back();
}
bool remove(
const value_type& val)
{
iterator it = std::find(collection_.begin(), collection_.end(), val);
if (it != collection_.end())
{
do_remove(it);
return true;
}
return false;
}
template<class UnaryPredicate>
bool remove_if(
UnaryPredicate pred)
{
iterator it = std::find_if(collection_.begin(), collection_.end(), pred);
if (it != collection_.end())
{
do_remove(it);
return true;
}
return false;
}
template <class InputIterator>
void assign(
InputIterator first,
InputIterator last)
{
size_type n = static_cast<size_type>(std::distance(first, last));
n = (std::min)(n, configuration_.maximum);
InputIterator value = first;
std::advance(value, n);
collection_.assign(first, value);
}
void assign(
size_type n,
const value_type& val)
{
n = (std::min)(n, configuration_.maximum);
collection_.assign(n, val);
}
void assign(
std::initializer_list<value_type> il)
{
size_type n = (std::min)(il.size(), configuration_.maximum);
collection_.assign(il.begin(), il.begin() + n);
}
reference at(
size_type pos)
{
return collection_.at(pos);
}
const_reference at(
size_type pos) const
{
return collection_.at(pos);
}
reference operator [](
size_type pos)
{
return collection_[pos];
}
const_reference operator [](
size_type pos) const
{
return collection_[pos];
}
reference front()
{
return collection_.front();
}
const_reference front() const
{
return collection_.front();
}
reference back()
{
return collection_.back();
}
const_reference back() const
{
return collection_.back();
}
iterator begin() noexcept
{
return collection_.begin();
}
const_iterator begin() const noexcept
{
return collection_.begin();
}
const_iterator cbegin() const noexcept
{
return collection_.cbegin();
}
iterator end() noexcept
{
return collection_.end();
}
const_iterator end() const noexcept
{
return collection_.end();
}
const_iterator cend() const noexcept
{
return collection_.cend();
}
reverse_iterator rbegin() noexcept
{
return collection_.rbegin();
}
const_reverse_iterator rbegin() const noexcept
{
return collection_.rbegin();
}
const_reverse_iterator crbegin() const noexcept
{
return collection_.crbegin();
}
reverse_iterator rend() noexcept
{
return collection_.rend();
}
const_reverse_iterator rend() const noexcept
{
return collection_.rend();
}
const_reverse_iterator crend() const noexcept
{
return collection_.crend();
}
bool empty() const noexcept
{
return collection_.empty();
}
size_type size() const noexcept
{
return collection_.size();
}
size_type capacity() const noexcept
{
return collection_.capacity();
}
size_type max_size() const noexcept
{
return (std::min)(configuration_.maximum, collection_.max_size());
}
void clear()
{
collection_.clear();
}
iterator erase(
const_iterator pos)
{
return collection_.erase(pos);
}
iterator erase(
const_iterator first,
const_iterator last)
{
return collection_.erase(first, last);
}
void pop_back()
{
collection_.pop_back();
}
value_type* data()
{
return collection_.data();
}
const value_type* data() const
{
return collection_.data();
}
operator const collection_type& () const noexcept
{
return collection_;
}
protected:
configuration_type configuration_;
collection_type collection_;
bool ensure_capacity()
{
size_type size = collection_.size();
size_type cap = collection_.capacity();
if (size == cap)
{
// collection is full, check resource limit
if (cap < configuration_.maximum)
{
// increase collection capacity
assert(configuration_.increment > 0);
cap += configuration_.increment;
cap = (std::min)(cap, configuration_.maximum);
collection_.reserve(cap);
}
else
{
return false;
}
}
return true;
}
template <typename Enabler = _KeepOrderEnabler>
typename std::enable_if<!Enabler::value, void>::type do_remove(
iterator it)
{
// Copy last element into the element being removed
if (it != --collection_.end())
{
*it = std::move(collection_.back());
}
// Then drop last element
collection_.pop_back();
}
template <typename Enabler = _KeepOrderEnabler>
typename std::enable_if<Enabler::value, void>::type do_remove(
iterator it)
{
collection_.erase(it);
}
};
} // namespace fastrtps
} // namespace eprosima
#endif /* FASTRTPS_UTILS_COLLECTIONS_RESOURCELIMITEDVECTOR_HPP_ */