/*
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() {
public:
using ManagedContainer::ManagedContainer;
/**
* 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(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 c.front(); }
const_reference front() const { return c.front(); }
reference back() { return c.back(); }
const_reference back() const { return c.back(); }
/* Insert and delete operations */
iterator insert(const_iterator position, Handle h)
{
value_type v = owner->acquire(h);
addManaged(v);
return c.insert(position, owner->acquire(h));
}
template
iterator insert(const_iterator position, InputIterator first,
InputIterator last)
{
bool first = true;
const_iterator pos = position;
for (InputIterator it = first; it != last; it++) {
if (first) {
first = false;
} else {
pos++;
}
pos = insert(pos, *it);
}
return pos;
}
iterator find(const Handle h)
{
for (iterator it = begin(); it != end(); it++) {
if (*it == h) {
return it;
}
}
return end();
}
const_iterator find(const Handle h) const
{
for (const_iterator it = cbegin(); it != cend(); it++) {
if (*it == h) {
return it;
}
}
return cend();
}
void push_back(Handle h)
{
Rooted rooted{h};
addManaged(rooted);
c.push_back(owner->acquire(rooted));
}
void pop_back()
{
if (!empty()) {
deleteElement(c.back());
}
c.pop_back();
}
iterator erase(iterator position)
{
deleteManaged(*position);
return c.erase(position);
}
iterator erase(iterator first, iterator last)
{
for (const_iterator it = first; it != last; it++) {
deleteManaged(*it);
}
return c.erase(first, last);
}
};
/**
* Special type of ManagedContainer based on an STL map.
*/
template
class ManagedGenericMap : public ManagedCollection {
private:
value_type acquirePair(std::pair> val)
{
return std::pair{val->first, 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 c.insert(v);
}
iterator insert(const_iterator position, std::pair> val)
{
value_type v = acquirePair(val);
addManaged(v);
return 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)
{
deleteManaged(*position);
return c.erase(position);
}
size_t erase(const key_type &k)
{
iterator pos = find(k);
if (pos != end()) {
erase(pos);
return 1;
}
return 0;
}
iterator erase(const_iterator first, const_iterator last)
{
for (const_iterator it = first; it != last; it++) {
deleteManaged(*it);
}
return c.erase(first, last);
}
iterator find(const key_type &k) { return c.find(k); }
const_iterator find(const key_type &k) const { return c.find(k); }
};
/**
* Special type of ManagedGenericList based on an STL vector.
*/
template
class ManagedVector : public ManagedGenericList>> {
public:
using ManagedContainer>>::ManagedContainer;
};
/**
* Special type of ManagedGenericMap based on an STL map.
*/
template
class ManagedMap : public ManagedGenericMap>> {
public:
using ManagedGenericMap>>::ManagedMap;
};
}
#endif /* _OUSIA_MANAGED_CONTAINERS_H_ */