/*
Ousía
Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#ifndef _OUSIA_MANAGED_CONTAINERS_H_
#define _OUSIA_MANAGED_CONTAINERS_H_
#include "Managed.hpp"
namespace ousia {
/**
* Template class which can be used to collect "Owned" refrences to a certain
* type of managed object. Do not use this class directly, use ManagedMap or
* ManagedVector instead. This class only provides functionality which is common
* to list and map containers (iterators and state).
*
* @param T is the type of the Managed object that should be managed.
* @param Collection should be a STL container of Owned
*/
template
class ManagedContainer {
public:
using collection_type = Collection;
using value_type = typename collection_type::value_type;
using reference = typename collection_type::reference;
using const_reference = typename collection_type::const_reference;
using iterator = typename collection_type::iterator;
using const_iterator = typename collection_type::const_iterator;
using size_type = typename collection_type::size_type;
protected:
/**
* Handle containing a reference to the owner of the collection.
*/
Handle owner;
/**
* Underlying STL collection.
*/
collection_type c;
protected:
/**
* Function which can be overridden by child classes to execute special code
* whenever a new element is added to the collection.
*/
virtual void addManaged(value_type h) {}
/**
* Function which can be overriden by child classes to execute special code
* whenever an element is removed from the collection.
*/
virtual void deleteManaged(value_type h) {}
public:
/**
* Constructor of the ManagedContainer class.
*
* @param owner is the managed object which owns the collection and all
* handles to other managed objects stored within.
*/
ManagedContainer(Handle owner) : owner(owner){};
/* State functions */
size_type size() const noexcept { return c.size(); }
bool empty() const noexcept { return c.empty(); }
/* Iterators */
iterator begin() { return c.begin(); }
iterator end() { return c.end(); }
iterator rbegin() { return c.rbegin(); }
iterator rend() { return c.rend(); }
const_iterator begin() const { return c.cbegin(); }
const_iterator end() const { return c.cend(); }
const_iterator cbegin() const { return c.cbegin(); }
const_iterator cend() const { return c.cend(); }
const_iterator rbegin() const { return c.crbegin(); }
const_iterator rend() const { return c.crend(); }
const_iterator crbegin() const { return c.crbegin(); }
const_iterator crend() const { return c.crend(); }
/* Clear function */
void clear() noexcept
{
for (const_iterator it = cbegin(); it != cend(); it++) {
deleteManaged(*it);
}
c.clear();
}
};
/**
* Template class which can be used to collect "Owned" refrences to a certain
* type of managed object. This class should be used in favour of other
* collections of handles, it takes care of acquiring an owned handle from the
* owner of this collection whenever a new element is added.
*
* @param T is the type of the Managed object that should be managed.
* @param Collection should be a STL list container of Owned
*/
template
class ManagedGenericList : public ManagedContainer {
private:
using Base = ManagedContainer;
public:
using Base::ManagedContainer;
using collection_type = typename Base::collection_type;
using value_type = typename Base::value_type;
using reference = typename Base::reference;
using const_reference = typename Base::const_reference;
using iterator = typename Base::iterator;
using const_iterator = typename Base::const_iterator;
using size_type = typename Base::size_type;
/**
* Initialize with an iterator from another collection.
*
* @param owner is the managed object which owns the collection and all
* handles to other managed objects stored within.
* @param first is an iterator pointing at the first element to be copied
* from some other collection.
* @param last is an iterator pointing at the last element to be copied
* from some other collection.
*/
template
ManagedGenericList(Handle owner, InputIterator first,
InputIterator last)
: ManagedContainer(owner)
{
insert(Base::c.begin(), first, last);
}
/**
* Initialize with another collection.
*
* @param owner is the managed object which owns the collection and all
* handles to other managed objects stored within.
* @param in is a reference at some other collection with content that
* should be copied.
*/
template
ManagedGenericList(Handle owner, const InputCollection &in)
: ManagedContainer(owner)
{
for (const auto &e : in) {
push_back(e);
}
}
/* Front and back */
reference front() { return Base::c.front(); }
const_reference front() const { return Base::c.front(); }
reference back() { return Base::c.back(); }
const_reference back() const { return Base::c.back(); }
/* Insert and delete operations */
iterator insert(const_iterator position, Handle h)
{
value_type v = Base::owner->acquire(h);
addManaged(v);
return Base::c.insert(position, v);
}
template
iterator insert(const_iterator position, InputIterator first,
InputIterator last)
{
bool atStart = true;
const_iterator pos = position;
for (InputIterator it = first; it != last; it++) {
if (atStart) {
atStart = false;
} else {
pos++;
}
pos = insert(pos, *it);
}
return pos;
}
iterator find(const Handle h)
{
for (iterator it = Base::begin(); it != Base::end(); it++) {
if (*it == h) {
return it;
}
}
return Base::end();
}
const_iterator find(const Handle h) const
{
for (const_iterator it = Base::cbegin(); it != Base::cend(); it++) {
if (*it == h) {
return it;
}
}
return Base::cend();
}
void push_back(Handle h)
{
value_type v = Base::owner->acquire(h);
this->addManaged(v);
Base::c.push_back(v);
}
void pop_back()
{
if (!Base::empty()) {
this->deleteManaged(back());
}
Base::c.pop_back();
}
iterator erase(iterator position)
{
this->deleteManaged(*position);
return Base::c.erase(position);
}
iterator erase(iterator first, iterator last)
{
for (const_iterator it = first; it != last; it++) {
this->deleteManaged(*it);
}
return Base::c.erase(first, last);
}
};
/**
* Special type of ManagedContainer based on an STL map.
*/
template
class ManagedGenericMap : public ManagedContainer {
private:
using Base = ManagedContainer;
public:
using Base::ManagedContainer;
using collection_type = typename Base::collection_type;
using value_type = typename Base::value_type;
using key_type = typename Base::key_type;
using reference = typename Base::reference;
using const_reference = typename Base::const_reference;
using iterator = typename Base::iterator;
using const_iterator = typename Base::const_iterator;
using size_type = typename Base::size_type;
private:
value_type acquirePair(std::pair> val)
{
return std::pair{val->first,
Base::owner->acquire(val->second)};
}
public:
/**
* Initialize with an iterator from another collection.
*
* @param owner is the managed object which owns the collection and all
* handles to other managed objects stored within.
* @param first is an iterator pointing at the first element to be copied
* from some other collection.
* @param last is an iterator pointing at the last element to be copied
* from some other collection.
*/
template
ManagedGenericMap(Handle owner, InputIterator first,
InputIterator last)
: ManagedContainer(owner)
{
insert(first, last);
}
/**
* Initialize with another collection.
*
* @param owner is the managed object which owns the collection and all
* handles to other managed objects stored within.
* @param in is a reference at some other collection with content that
* should be copied.
*/
template
ManagedGenericMap(Handle owner, const InputCollection &in)
: ManagedContainer(owner)
{
for (const auto &e : in) {
insert(*in);
}
}
std::pair insert(std::pair> val)
{
value_type v = acquirePair(val);
addManaged(v);
return Base::c.insert(v);
}
iterator insert(const_iterator position, std::pair> val)
{
value_type v = acquirePair(val);
addManaged(v);
return Base::c.insert(position, v);
}
template
void insert(InputIterator first, InputIterator last)
{
for (auto it = first; it != last; it++) {
insert(acquirePair);
}
}
iterator erase(const_iterator position)
{
Base::deleteManaged(*position);
return Base::c.erase(position);
}
size_t erase(const key_type &k)
{
iterator pos = find(k);
if (pos != Base::end()) {
erase(pos);
return 1;
}
return 0;
}
iterator erase(const_iterator first, const_iterator last)
{
for (const_iterator it = first; it != last; it++) {
Base::deleteManaged(*it);
}
return Base::c.erase(first, last);
}
iterator find(const key_type &k) { return Base::c.find(k); }
const_iterator find(const key_type &k) const { return Base::c.find(k); }
};
/**
* Special type of ManagedGenericList based on an STL vector.
*/
template
class ManagedVector : public ManagedGenericList>> {
public:
using ManagedGenericList>>::ManagedGenericList;
};
/**
* Special type of ManagedGenericMap based on an STL map.
*/
template
class ManagedMap : public ManagedGenericMap>> {
public:
using ManagedGenericMap>>::ManagedGenericMap;
};
}
#endif /* _OUSIA_MANAGED_CONTAINERS_H_ */