/*! \file picontainers.h * \brief Generic containers * * This file declare all containers and useful macros * to use them */ /* PIP - Platform Independent Primitives Generic containers Copyright (C) 2014 Ivan Pelipenko peri4ko@gmail.com 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 PICONTAINERS_H #define PICONTAINERS_H #include "pivector.h" template class PIP_EXPORT PIPair { public: PIPair() {first = Type0(); second = Type1();} PIPair(const Type0 & value0, const Type1 & value1) {first = value0; second = value1;} Type0 first; Type1 second; }; template inline bool operator <(const PIPair & value0, const PIPair & value1) {return value0.first < value1.first;} template inline bool operator ==(const PIPair & value0, const PIPair & value1) {return (value0.first == value1.first) && (value0.second == value1.second);} template inline bool operator !=(const PIPair & value0, const PIPair & value1) {return (value0.first != value1.first) || (value0.second != value1.second);} template inline std::ostream & operator <<(std::ostream & s, const PIPair & v) {s << "(" << v.first << ", " << v.second << ")"; return s;} template inline PICout operator <<(PICout s, const PIPair & v) {s.space(); s.setControl(0, true); s << "(" << v.first << ", " << v.second << ")"; s.restoreControl(); return s;} #include "pistack.h" #include "piqueue.h" #include "pimap.h" #ifdef DOXYGEN /*! \def piForeach(i,c) * \brief Macro for iterate any container * \details Use this macros instead of standard "for" * to get read/write access to each element of container. * Pass direction is direct \n * Example: \snippet picontainers.cpp foreach */ /*! \def piForeachC(i,c) * \brief Macro for iterate any container only for read * \details Use this macros instead of standard "for" * to get read access to each element of container. * Pass direction is direct \n * Example: \snippet picontainers.cpp foreachC */ /*! \def piForeachR(i,c) * \brief Macro for iterate any container with reverse direction * \details Use this macros instead of standard "for" * to get read/write access to each element of container. * Pass direction is reverse \n * Example: \snippet picontainers.cpp foreachR */ /*! \def piForeachCR(i,c) * \brief Macro for iterate any container only for read with reverse direction * \details Use this macros instead of standard "for" * to get read access to each element of container. * Pass direction is reverse \n * Example: \snippet picontainers.cpp foreachCR */ #endif #ifdef CC_GCC template class _PIForeach { public: _PIForeach(Type & t): _t(t) {_it = _t.begin(); _break = false;} typename Type::value_type _var; typename Type::iterator _it; Type & _t; bool _break; inline bool isEnd() {return _it == _t.end();} inline void operator ++() {_it++; _break = false;} }; template class _PIForeachR { public: _PIForeachR(Type & t): _t(t) {_rit = _t.rbegin(); _break = false;} typename Type::value_type _var; typename Type::reverse_iterator _rit; Type & _t; bool _break; inline bool isEnd() {return _rit == _t.rend();} inline void operator ++() {_rit++; _break = false;} }; template class _PIForeachC { public: _PIForeachC(const Type & t): _t(t) {_it = _t.begin(); _break = false;} typename Type::value_type _var; typename Type::const_iterator _it; const Type & _t; bool _break; inline bool isEnd() {return _it == _t.end();} inline void operator ++() {_it++; _break = false;} }; template class _PIForeachCR { public: _PIForeachCR(const Type & t): _t(t) {_rit = _t.rbegin(); _break = false;} typename Type::value_type _var; typename Type::const_reverse_iterator _rit; const Type & _t; bool _break; inline bool isEnd() {return _rit == _t.rend();} inline void operator ++() {_rit++; _break = false;} }; #define piForeach(i,c) for(_PIForeach _for(c); !_for.isEnd(); ++_for) \ for(i(*_for._it); !_for._break; _for._break = true) #define piForeachR(i,c) for(_PIForeachR _for(c); !_for.isEnd(); ++_for) \ for(i(*_for._rit); !_for._break; _for._break = true) #define piForeachA(i,c) for(_PIForeach _for(c); !_for.isEnd(); ++_for) \ for(typeof(_for._var) & i(*_for._it); !_for._break; _for._break = true) #define piForeachAR(i,c) for(_PIForeachR _for(c); !_for.isEnd(); ++_for) \ for(typeof(_for._var) & i(*_for._rit); !_for._break; _for._break = true) #define piForeachC(i,c) for(_PIForeachC _for(c); !_for.isEnd(); ++_for) \ for(const i(*_for._it); !_for._break; _for._break = true) #define piForeachCR(i,c) for(_PIForeachCR _for(c); !_for.isEnd(); ++_for) \ for(const i(*_for._rit); !_for._break; _for._break = true) #define piForeachCA(i,c) for(_PIForeachC _for(c); !_for.isEnd(); ++_for) \ for(const typeof(_for._var) & i(*_for._it); !_for._break; _for._break = true) #define piForeachCAR(i,c) for(_PIForeachCR _for(c); !_for.isEnd(); ++_for) \ for(const typeof(_for._var) & i(*_for._rit); !_for._break; _for._break = true) #define piForeachRA piForeachAR #define piForeachAC piForeachCA #define piForeachCRA piForeachCAR #define piForeachARC piForeachCAR #define piForeachACR piForeachCAR #define piForeachRCA piForeachCAR #define piForeachRAC piForeachCAR #else struct _PIForeachBase {mutable bool _break;}; template class _PIForeach: public _PIForeachBase { public: _PIForeach(Type & t, bool i = false): _t(t), _inv(i) {if (_inv) _rit = _t.rbegin(); else _it = _t.begin(); _break = false;} mutable typename Type::value_type _var; mutable typename Type::iterator _it; mutable typename Type::reverse_iterator _rit; Type & _t; bool _inv; bool isEnd() {if (_inv) return _rit == _t.rend(); else return _it == _t.end();} void operator ++() {if (_inv) _rit++; else _it++; _break = false;} }; template class _PIForeachC: public _PIForeachBase { public: _PIForeachC(const Type & t, bool i = false): _t(t), _inv(i) {if (_inv) _rit = _t.rbegin(); else _it = _t.begin(); _break = false;} mutable typename Type::value_type _var; mutable typename Type::const_iterator _it; mutable typename Type::const_reverse_iterator _rit; const Type & _t; bool _inv; bool isEnd() {if (_inv) return _rit == _t.rend(); else return _it == _t.end();} void operator ++() {if (_inv) _rit++; else _it++; _break = false;} }; template inline _PIForeach _PIForeachNew(T & t, bool i = false) {return _PIForeach(t, i);} template inline _PIForeach * _PIForeachCast(_PIForeachBase & c, T & ) {return static_cast<_PIForeach * >(&c);} template inline _PIForeachC _PIForeachNewC(const T & t, bool i = false) {return _PIForeachC(t, i);} template inline _PIForeachC * _PIForeachCastC(_PIForeachBase & c, const T & ) {return static_cast<_PIForeachC * >(&c);} #define piForeach(i,c) for(_PIForeachBase & _for = _PIForeachNew(c); !_PIForeachCast(_for, c)->isEnd(); ++(*_PIForeachCast(_for, c))) \ for(i = *(_PIForeachCast(_for, c)->_it); !_for._break; _for._break = true) #define piForeachR(i,c) for(_PIForeachBase & _for = _PIForeachNew(c, true); !_PIForeachCast(_for, c)->isEnd(); ++(*_PIForeachCast(_for, c))) \ for(i = *(_PIForeachCast(_for, c)->_rit); !_for._break; _for._break = true) #define piForeachC(i,c) for(_PIForeachBase & _for = _PIForeachNewC(c); !_PIForeachCastC(_for, c)->isEnd(); ++(*_PIForeachCastC(_for, c))) \ for(const i = *(_PIForeachCastC(_for, c)->_it); !_for._break; _for._break = true) #define piForeachCR(i,c) for(_PIForeachBase & _for = _PIForeachNewC(c, false); !_PIForeachCastC(_for, c)->isEnd(); ++(*_PIForeachCastC(_for, c))) \ for(const i = *(_PIForeachCastC(_for, c)->_rit); !_for._break; _for._break = true) #endif #define piForeachRC piForeachCR #define piForTimes(c) for(int _i##c = 0; _i##c < c; ++_i##c) template > class PIP_EXPORT PIList: public list { typedef PIList _CList; typedef list _stlc; public: PIList() {piMonitor.containers++;} PIList(const Type & value) {piMonitor.containers++; _stlc::resize(1, value);} PIList(const Type & v0, const Type & v1) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1);} PIList(const Type & v0, const Type & v1, const Type & v2) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2);} PIList(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2); _stlc::push_back(v3);} PIList(uint size, const Type & value = Type()) {piMonitor.containers++; _stlc::resize(size, value);} ~PIList() {piMonitor.containers--;} Type & operator [](uint index) {return (*this)[index];} Type & operator [](uint index) const {return (*this)[index];} const Type * data(uint index = 0) const {return &(*this)[index];} Type * data(uint index = 0) {return &(*this)[index];} int size_s() const {return static_cast(_stlc::size());} bool isEmpty() const {return _stlc::empty();} bool has(const Type & t) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) return true; return false;} int etries(const Type & t) const {int ec = 0; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) ++ec; return ec;} _CList & fill(const Type & t) {_stlc::assign(_stlc::size(), t); return *this;} _CList & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;} _CList & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;} _CList & insert(uint pos, const Type & t) {_stlc::insert(_stlc::begin() + pos, t); return *this;} _CList & operator <<(const Type & t) {_stlc::push_back(t); return *this;} PIVector toVector() {PIVector v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;} }; /*! \brief Set of any type * \details This class used to store collection of unique elements * of any type. You can only add values to set with \a operator<< or * with function \a insert(). You can discover if value already in * set with \a operator[] or with function \a find(). These function * has logarithmic complexity. */ template, typename Allocator = std::allocator > class PIP_EXPORT PISet: public set { typedef PISet _CSet; typedef set _stlc; public: //! Contructs an empty set PISet() {piMonitor.containers++;} //! Contructs set with one element "value" PISet(const Type & value) {piMonitor.containers++; _stlc::resize(1, value);} //! Contructs set with elements "v0" and "v1" PISet(const Type & v0, const Type & v1) {piMonitor.containers++; _stlc::insert(v0); _stlc::insert(v1);} //! Contructs set with elements "v0", "v1" and "v2" PISet(const Type & v0, const Type & v1, const Type & v2) {piMonitor.containers++; _stlc::insert(v0); _stlc::insert(v1); _stlc::insert(v2);} //! Contructs set with elements "v0", "v1", "v2" and "v3" PISet(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {piMonitor.containers++; _stlc::insert(v0); _stlc::insert(v1); _stlc::insert(v2); _stlc::insert(v3);} ~PISet() {piMonitor.containers--;} //! Returns elements count int size_s() const {return static_cast(_stlc::size());} //! Returns if set is empty bool isEmpty() const {return _stlc::empty();} #ifdef DOXYGEN //! Clear th set void clear(); //! Insert element "t" if it doesn`t exists in this set void insert(const Type & t); #endif _CSet & remove(uint index) {_stlc::erase(_stlc::begin() + index); return *this;} _CSet & remove(uint index, uint count) {_stlc::erase(_stlc::begin() + index, _stlc::begin() + index + count); return *this;} _CSet & operator <<(const Type & t) {_stlc::insert(t); return *this;} //! Returns if element "t" exists in this set bool operator [](const Type & t) {return _stlc::find(t) != _stlc::end();} //! Returns content of set as PIVector PIVector toVector() {PIVector v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;} }; template > class PIP_EXPORT PIDeque: public deque { typedef PIDeque _CDeque; typedef deque _stlc; public: PIDeque() {piMonitor.containers++;} PIDeque(const Type & value) {piMonitor.containers++; _stlc::resize(1, value);} PIDeque(const Type & v0, const Type & v1) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1);} PIDeque(const Type & v0, const Type & v1, const Type & v2) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2);} PIDeque(const Type & v0, const Type & v1, const Type & v2, const Type & v3) {piMonitor.containers++; _stlc::push_back(v0); _stlc::push_back(v1); _stlc::push_back(v2); _stlc::push_back(v3);} ~PIDeque() {piMonitor.containers--;} int size_s() const {return static_cast(_stlc::size());} bool isEmpty() const {return _stlc::empty();} bool has(const Type & t) const {for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) return true; return false;} int etries(const Type & t) const {int ec = 0; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) if (t == *i) ++ec; return ec;} _CDeque & operator <<(const Type & t) {_CDeque::push_back(t); return *this;} PIVector toVector() {PIVector v; for (typename _stlc::const_iterator i = _stlc::begin(); i != _stlc::end(); ++i) v << *i; return v;} }; #endif // PICONTAINERS_H