/*! \file picontainers.h * \brief Base for generic containers * * This file declare all containers and useful macros * to use them */ /* PIP - Platform Independent Primitives Base for generic containers Copyright (C) 2018 Ivan Pelipenko peri4ko@yandex.ru 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 "picout.h" #ifdef PIP_DEBUG # include #endif #ifndef assert # define assert(x) #endif #ifdef MAC_OS # include #else # include #endif #include #include #ifndef PIP_MEMALIGN_BYTES # define PIP_MEMALIGN_BYTES (sizeof(void*)*4) #endif #ifdef WINDOWS # ifdef CC_GCC # define amalloc(s) __mingw_aligned_malloc(s, PIP_MEMALIGN_BYTES) # define afree(p) __mingw_aligned_free(p) # else # ifdef CC_VC # define amalloc(s) _aligned_malloc(s, PIP_MEMALIGN_BYTES) # define afree(p) _aligned_free(p) # endif # endif #else # define amalloc(s) aligned_alloc(PIP_MEMALIGN_BYTES, s) # define afree(p) free(p) #endif #ifdef DOXYGEN /*!\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 */ # define piForeach(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 */ # define piForeachC(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 */ # define piForeachR(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 */ # define piForeachCR(i,c) /*!\brief Macro for break from any piForeach* loop * \details \warning C++ ordinary "break" doesn`t work inside piForeach* * loops! Always use "piBreak" instead! */ # define piBreak #else # define piBreak {_for._end = true; break;} # define piForTimes(c) for(int _i##c = 0; _i##c < c; ++_i##c) #ifdef CC_GCC template class _PIForeach { public: _PIForeach(Type & t): _t(t), _break(false), _end(false) {_it = _t.begin();} typename Type::value_type _var; typename Type::iterator _it; Type & _t; bool _break, _end; inline bool isEnd() {return _it == _t.end();} inline void operator ++() {if (_end) _it = _t.end(); else _it++; _break = false;} }; template class _PIForeachR { public: _PIForeachR(Type & t): _t(t), _break(false), _end(false) {_rit = _t.rbegin();} typename Type::value_type _var; typename Type::reverse_iterator _rit; Type & _t; bool _break, _end; inline bool isEnd() {return _rit == _t.rend();} inline void operator ++() {if (_end) _rit = _t.rend(); else _rit++; _break = false;} }; template class _PIForeachC { public: _PIForeachC(const Type & t): _t(t), _break(false), _end(false) {_it = _t.begin();} typename Type::value_type _var; typename Type::const_iterator _it; const Type & _t; bool _break, _end; inline bool isEnd() {return _it == _t.end();} inline void operator ++() {if (_end) _it = _t.end(); else _it++; _break = false;} }; template class _PIForeachCR { public: _PIForeachCR(const Type & t): _t(t), _break(false), _end(false) {_rit = _t.rbegin();} typename Type::value_type _var; typename Type::const_reverse_iterator _rit; const Type & _t; bool _break, _end; inline bool isEnd() {return _rit == _t.rend();} inline void operator ++() {if (_end) _rit = _t.rend(); else _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, _end;}; template class _PIForeach: public _PIForeachBase { public: _PIForeach(Type & t, bool i = false): _break(false), _end(false), _t(t), _inv(i) {if (_inv) _rit = _t.rbegin(); else _it = _t.begin();} 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) {if (_end) _rit = _t.rend(); else _rit++;} else {if (_end) _it = _t.end(); else _it++;} _break = false;} }; template class _PIForeachC: public _PIForeachBase { public: _PIForeachC(const Type & t, bool i = false): _break(false), _end(false), _t(t), _inv(i) {if (_inv) _rit = _t.rbegin(); else _it = _t.begin();} 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) {if (_end) _rit = _t.rend(); else _rit++;} else {if (_end) _it = _t.end(); 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 #endif // DOXYGEN #endif // PICONTAINERS_H