I worked under the erroneous assumption, that Doxygen will use its internal entity-IDs as the link-IDs when generating mardown-links. Yes, this seemed logical and this would be the way I'd implement it.... But seemingly, Doxygen is not so consistent when it comes to questions of syntax. The same holds true for markdown, which lacking a coherent definition anyway. Another problem is that Doxygen's auto-link generation frequently fails, for reasons not yet clear to me. Sometimes it seems to be necessary to give it a nudge by including the \ref command. While I'm not willing to go into focussed invstigation of Doxygen syntax right now, at least I've done a search-and-replace to remove the malformed links I've written the last days
217 lines
6 KiB
C++
217 lines
6 KiB
C++
/*
|
|
ITER-CURSOR.hpp - wrap bidirectional STL container iterators
|
|
|
|
Copyright (C) Lumiera.org
|
|
2015, Hermann Vosseler <Ichthyostega@web.de>
|
|
|
|
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 2 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, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
|
|
/** @file iter-cursor.hpp
|
|
** An iterator with the ability to switch direction.
|
|
** This wrapper relies on the ability of typical STL container iterators
|
|
** to work in both directions, similar to std::reverse_iterator.
|
|
** Yet it is a single, self-contained element and in compliance to the
|
|
** ["Lumiera Forward Iterator"](iter-adapter.hpp) concept. But it has
|
|
** the additional ability to [switch the working direction](\ref IterCursor::switchDir).
|
|
**
|
|
** @see IterCursor_test
|
|
** @see iter-adapter.hpp
|
|
** @see [usage example](event-log.hpp)
|
|
**
|
|
*/
|
|
|
|
|
|
#ifndef SRC_LIB_ITER_CURSOR_H
|
|
#define SRC_LIB_ITER_CURSOR_H
|
|
|
|
|
|
#include "lib/error.hpp"
|
|
#include "lib/iter-adapter.hpp"
|
|
|
|
#include <type_traits>
|
|
#include <utility>
|
|
|
|
|
|
namespace lib {
|
|
namespace iter {
|
|
|
|
/**
|
|
* @internal implementation for a "gear switching" iterator,
|
|
* based on STL container iterators.
|
|
*/
|
|
template<class IT>
|
|
class CursorGear
|
|
{
|
|
bool backwards_{false};
|
|
const IT start_;
|
|
const IT end_;
|
|
|
|
IT pos_;
|
|
|
|
|
|
public:
|
|
typedef typename iter::TypeBinding<IT>::pointer pointer;
|
|
typedef typename iter::TypeBinding<IT>::reference reference;
|
|
typedef typename std::remove_reference<reference>::type value_type; ///< @note will be const for const iterators
|
|
|
|
|
|
CursorGear()
|
|
: start_()
|
|
, end_()
|
|
, pos_()
|
|
{ }
|
|
|
|
CursorGear (IT&& begin, IT&& end)
|
|
: start_(std::forward<IT>(begin))
|
|
, end_(std::forward<IT>(end))
|
|
, pos_(start_)
|
|
{ }
|
|
|
|
// using default copy/assignment
|
|
|
|
|
|
void
|
|
reverse(bool backwards)
|
|
{
|
|
if (backwards != backwards_) reverse();
|
|
}
|
|
|
|
void
|
|
reverse()
|
|
{
|
|
if (start_ == end_) return;
|
|
if (backwards_)
|
|
{
|
|
if (pos_ != start_) --pos_;
|
|
backwards_ = false;
|
|
}
|
|
else
|
|
{
|
|
if (pos_ != end_) ++pos_;
|
|
backwards_ = true;
|
|
}
|
|
}
|
|
|
|
/* === Iteration control API for IterStateWrapper == */
|
|
|
|
friend bool
|
|
checkPoint (CursorGear const& gear)
|
|
{
|
|
return gear.backwards_? gear.pos_ != gear.start_
|
|
: gear.pos_ != gear.end_;
|
|
}
|
|
|
|
friend reference
|
|
yield (CursorGear const& gear)
|
|
{
|
|
return gear.backwards_? *(gear.pos_-1)
|
|
: *(gear.pos_);
|
|
}
|
|
|
|
friend void
|
|
iterNext (CursorGear & gear)
|
|
{
|
|
if (gear.backwards_)
|
|
--gear.pos_;
|
|
else
|
|
++gear.pos_;
|
|
}
|
|
|
|
|
|
friend bool
|
|
operator== (CursorGear const& g1, CursorGear const& g2)
|
|
{
|
|
return (not checkPoint(g1) and not checkPoint(g2)) // note: all exhausted iters are equal
|
|
or ( g1.pos_ == g2.pos_
|
|
and g1.backwards_ == g2.backwards_
|
|
and g1.start_ == g2.start_
|
|
and g1.end_ == g2.end_
|
|
);
|
|
}
|
|
};
|
|
|
|
|
|
} // namespace iter
|
|
|
|
|
|
|
|
|
|
/**
|
|
* A cursor-like iterator with the ability to switch iteration direction.
|
|
* It can be built on top of any bidirectional STL iterator or similar entity,
|
|
* which has an `--` operator. Initially, IterCursor will operate in forward
|
|
* direction; irrespective of the current direction, it always fulfils the
|
|
* ["Lumiera Forward Iterator"](iter-adapter.hpp) concept, i.e. it can be
|
|
* iterated until exhaustion, in which case it will evaluate to bool(false).
|
|
* @note IterCursor instances can be equality compared, also taking the
|
|
* current direction into account. As a special case, all
|
|
* exhausted iterators are treated as equal.
|
|
*/
|
|
template<class IT>
|
|
class IterCursor
|
|
: public IterStateWrapper<typename iter::CursorGear<IT>::value_type, iter::CursorGear<IT>>
|
|
{
|
|
using _Core = iter::CursorGear<IT>;
|
|
using _Parent = IterStateWrapper<typename _Core::value_type, _Core>;
|
|
|
|
public:
|
|
IterCursor() { }
|
|
|
|
template<class CON>
|
|
explicit
|
|
IterCursor (CON& container)
|
|
: _Parent(_Core(container.begin(), container.end()))
|
|
{ }
|
|
|
|
IterCursor (IT&& begin, IT&& end)
|
|
: _Parent(_Core(std::forward<IT>(begin), std::forward<IT>(end)))
|
|
{ }
|
|
|
|
|
|
/**
|
|
* change the orientation of iteration.
|
|
* A forward oriented iteration will continue backwards,
|
|
* and vice versa. This operation can even be invoked
|
|
* on an already exhausted iterator, in which case
|
|
* it will turn back in reversed direction.
|
|
*/
|
|
IterCursor&
|
|
switchDir()
|
|
{
|
|
this->stateCore().reverse();
|
|
return *this;
|
|
}
|
|
|
|
IterCursor&
|
|
switchForwards()
|
|
{
|
|
this->stateCore().reverse(false);
|
|
return *this;
|
|
}
|
|
|
|
IterCursor&
|
|
switchBackwards()
|
|
{
|
|
this->stateCore().reverse(true);
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
|
|
} // namespace lib
|
|
#endif /*SRC_LIB_ITER_CURSOR_H*/
|