diff --git a/src/lib/iter-index.hpp b/src/lib/iter-index.hpp new file mode 100644 index 000000000..93b058289 --- /dev/null +++ b/src/lib/iter-index.hpp @@ -0,0 +1,144 @@ +/* + ITER-INDEX.hpp - iterator with indexed random-access to referred container + + Copyright (C) Lumiera.org + 2024, Hermann Vosseler + + 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-index.hpp + ** Iterator-style access handle to a referred container with subscript index. + ** This wrapper packages a current index number and a back-link to some data container + ** with subscript operator and range check. This allows to hand out a navigable access point + ** to a processing algorithm while abstracting away the actual data storage. Besides usage + ** as »Lumiera Forward Iterator«, the current access position can be retrieved directly + ** and it can be relocated to another valid index position; this implies also the ability + ** to re-set the iteration to the container's start. + ** + ** @see IterIndex_test + ** @see iter-adapter.hpp + ** @see [usage example](\ref lib::TextTemplate::InstanceCore) + ** + */ + + +#ifndef SRC_LIB_ITER_INDEX_H +#define SRC_LIB_ITER_INDEX_H + + +#include "lib/iter-adapter.hpp" + +//#include +//#include + + +namespace lib { + + namespace {// Implementation of the access core + + template + struct IndexAccessCore + { + PTR data_{}; + size_t idx_{0}; + + using ResVal = decltype(data_->operator[](0)); + + using value_type = typename meta::RefTraits::Value; + using reference = typename meta::RefTraits::Reference; + + using IterWrapper = lib::IterStateWrapper; + + bool + checkPoint() const + { + return isValidIDX(idx_); + } + + reference + yield() const + { + return (*data_)[idx_]; + } + + void + iterNext() + { + ++idx_; + } + + + bool + isValidIDX (size_t idx) const + { + return bool(data_) + and idx < data_->size(); + } + + + friend bool operator== (IndexAccessCore const& c1, IndexAccessCore const& c2) + { + return c1.data_ == c2.data_ and (not c1.data_ or c1.idx_ == c2.idx_); + } + friend bool operator!= (IndexAccessCore const& c1, IndexAccessCore const& c2) + { + return not (c1 == c2); + } + }; + + }//(End)Implementation + + + /** + * + */ + template + class IterIndex + : public IndexAccessCore::IterWrapper + { + using _Cor = IndexAccessCore; + using _Par = typename _Cor::IterWrapper; + + public: + IterIndex() = default; + IterIndex (CON& dataContainer) + : _Par{_Cor{&dataContainer, 0}} + { } + + + size_t + getIDX() const + { + _Par::__throw_if_empty(); + return const_cast(this)->stateCore().idx_; + } + + void + setIDX (size_t newIDX) + { + auto& core = _Par::stateCore(); + if (not core.isValidIDX (newIDX)) + throw lumiera::error::Invalid ("Attempt to set index out of bounds", + lumiera::error::LUMIERA_ERROR_INDEX_BOUNDS); + core.idx_ = newIDX; + } + }; + + +} // namespace lib +#endif /*SRC_LIB_ITER_INDEX_H*/ diff --git a/tests/library/iter-index-test.cpp b/tests/library/iter-index-test.cpp new file mode 100644 index 000000000..611fb617a --- /dev/null +++ b/tests/library/iter-index-test.cpp @@ -0,0 +1,265 @@ +/* + IterIndex(Test) - verify index access packaged as iterator handle + + Copyright (C) Lumiera.org + 2024, Hermann Vosseler + + 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-index-test.cpp + ** unit test \ref IterIndex_test + */ + + + +#include "lib/test/run.hpp" +#include "lib/iter-index.hpp" +#include "lib/test/test-helper.hpp" +#include "lib/iter-explorer.hpp" +#include "lib/format-util.hpp" +#include "lib/util.hpp" + +#include + + + +namespace lib { +namespace test{ + + using ::Test; + using util::join; + using util::isnil; + using std::vector; + + using LERR_(ITER_EXHAUST); + using LERR_(INDEX_BOUNDS); + + + namespace { // test fixture + + const uint NUM_ELMS = 10; + + using Numz = vector; + using Iter = IterIndex; + using CIter = IterIndex; + + inline Numz + makeNumz() + { + Numz numz; + for (uint i=0; i + void + verifyComparisons (IT const& ii) + { + IT i1(ii); + IT i2(ii); + IT iN; + CHECK ( isnil (iN)); + CHECK (!isnil (i1)); + CHECK (!isnil (i2)); + + CHECK (i1 == i2); CHECK (i2 == i1); + CHECK (i1 != iN); CHECK (iN != i1); + CHECK (i2 != iN); CHECK (iN != i2); + + ++i1; + CHECK (i1 != i2); + CHECK (i1 != iN); + + ++i2; + CHECK (i1 == i2); + CHECK (i1 != iN); + CHECK (i2 != iN); + + while (++i1) { } + CHECK (isnil(i1)); + CHECK (i1 != i2); + CHECK (i1 == iN); + + while (++i2) { } + CHECK (isnil(i2)); + CHECK (i2 == i1); + CHECK (i2 == iN); + } + }; + + LAUNCHER (IterIndex_test, "unit common"); + + +}} // namespace lib::test + diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 8f6b652b8..fdad6391e 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -112553,16 +112553,13 @@ std::cout << tmpl.render({"what", "World"}) << s - - - +

das bedeutet: nachdem ein nested-context geöffnet wurde, müssen wir einen State erlangen, auf dem transparent genauso gearbeitet werden kann, wie auf dem initialen / top-level-State

- -
+
@@ -112577,16 +112574,13 @@ std::cout << tmpl.render({"what", "World"}) << s - - - +

weil sie im Einzelfall auch komplexer sein kann, und im Besonderen eine parent-Verknüpfung beinhaltet

- -
+
@@ -112846,6 +112840,7 @@ std::cout << tmpl.render({"what", "World"}) << s + @@ -112867,16 +112862,13 @@ std::cout << tmpl.render({"what", "World"}) << s - - - +

will sagen, der Standardfall ist, lediglich auf eine Map per Key zuzugreifen — und die gesamte Datenstruktur ist hierauf zu optimieren

- -
+
@@ -112908,6 +112900,13 @@ std::cout << tmpl.render({"what", "World"}) << s + + + + + + + @@ -112940,6 +112939,64 @@ std::cout << tmpl.render({"what", "World"}) << s
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ uuund fertig — C++ ist toll +

+ +
+ +
+
+ + + + + + + + + + + + +
@@ -120672,6 +120729,31 @@ class Something
+ + + + + + + + + + + + + + +

+ Konversion string_view ⟼ string kopiert die Daten +

+ +
+ + + + + +