From 5e1c25aaf58107b03200e90f13cd000bc9211354 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 24 Sep 2017 22:41:45 +0200 Subject: [PATCH] UI-Coordinates: extract PathArray base abstraction into a library class --- src/gui/interact/ui-coord.hpp | 86 +-------------- src/lib/path-array.hpp | 165 ++++++++++++++++++++++++++++ tests/15library.tests | 5 + tests/library/path-array-test.cpp | 177 ++++++++++++++++++++++++++++++ 4 files changed, 351 insertions(+), 82 deletions(-) create mode 100644 src/lib/path-array.hpp create mode 100644 tests/library/path-array-test.cpp diff --git a/src/gui/interact/ui-coord.hpp b/src/gui/interact/ui-coord.hpp index af84f65cc..1fc53e048 100644 --- a/src/gui/interact/ui-coord.hpp +++ b/src/gui/interact/ui-coord.hpp @@ -39,6 +39,8 @@ ** ** @todo WIP 9/2017 first draft ////////////////////////////////////////////////////////////////////////////TICKET #1106 generic UI coordinate system ** + ** @note UICoord is designed with immutability in mind; possibly we may decide to disallow assignment. + ** ** @see UICoord_test ** @see id-scheme.hpp ** @see view-spec-dsl.hpp @@ -51,11 +53,10 @@ #include "lib/error.hpp" #include "lib/symbol.hpp" -#include "lib/iter-adapter.hpp" +#include "lib/path-array.hpp" //#include #include -#include //#include @@ -66,87 +67,8 @@ namespace interact { using std::string; using lib::Literal; -// class GlobalCtx; - - /** - * @internal Base abstraction for path-like topological coordinates. - */ - class PathArray - { - public: - template - explicit - PathArray (ARGS&& ...args) - { - UNIMPLEMENTED ("initialise path array components"); - } - - // standard copy operations acceptable - - - size_t - size() const - { - UNIMPLEMENTED ("path implementation storage"); - } - - bool - empty() const - { - UNIMPLEMENTED ("path implementation storage"); - } - - - Literal - operator[] (size_t idx) - { - UNIMPLEMENTED ("path implementation storage"); - } - - - protected: /* ==== Iteration control API for IterAdapter ==== */ - - /** Implementation of Iteration-logic: pull next element. */ - friend void - iterNext (const PathArray* src, Literal* pos) - { - ++pos; - checkPoint (src,pos); - } - - /** Implementation of Iteration-logic: detect iteration end. */ - friend bool - checkPoint (const PathArray* src, Literal* pos) - { - REQUIRE (src); - if ((pos != nullptr) && (pos != src->storage_end())) - return true; - else - { - pos = nullptr; - return false; - } } - - public: - using iterator = lib::IterAdapter; - using const_iterator = iterator; - - iterator begin() const { UNIMPLEMENTED ("content iteration"); } - iterator end() const { UNIMPLEMENTED ("content iteration"); } - - friend iterator begin(PathArray const& pa) { return pa.begin();} - friend iterator end (PathArray const& pa) { return pa.end(); } - - private: - Literal* - storage_end() const - { - UNIMPLEMENTED ("path implementation storage"); - } - }; - enum UIPathElm { UIC_WINDOW, @@ -166,7 +88,7 @@ namespace interact { * @todo initial draft as of 9/2017 */ class UICoord - : public PathArray + : public lib::PathArray { public: diff --git a/src/lib/path-array.hpp b/src/lib/path-array.hpp new file mode 100644 index 000000000..0ba5f014a --- /dev/null +++ b/src/lib/path-array.hpp @@ -0,0 +1,165 @@ +/* + PATH-ARRAY.hpp - sequence of path-like component-IDs in fixed storage + + Copyright (C) Lumiera.org + 2017, 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 path-array.hpp + ** Foundation abstraction to implement path-like component sequences. + ** This library class can be used to build a path abstraction for data structure access + ** or some similar topological coordinate system, like e.g. [UI coordinates](\ref ui-coord.hpp) + ** A PathArray is an iterable sequence of literal component IDs, implemented as tuple of `Literal*` + ** held in fixed inline storage with possible heap allocated (and thus unlimited) extension storage. + ** It offers range checks, standard iteration and array-like indexed component access; as a whole + ** it is copyable, while actual components are immutable after construction. + ** + ** @todo WIP 9/2017 first draft ////////////////////////////////////////////////////////////////////////////TICKET #1106 generic UI coordinate system + ** + ** @see PathArray_test + ** @see UICoord_test + ** @see gui::interact::UICoord + ** @see view-spec-dsl.hpp + */ + + +#ifndef LIB_PATH_ARRAY_H +#define LIB_PATH_ARRAY_H + +#include "lib/error.hpp" +#include "lib/symbol.hpp" +#include "lib/iter-adapter.hpp" + +//#include +#include +//#include + + +namespace lib { + +// using std::unique_ptr; + using std::string; + using lib::Literal; + +// class GlobalCtx; + + + + /** + * @internal Base abstraction for path-like topological coordinates. + */ + class PathArray + { + public: + template + explicit + PathArray (ARGS&& ...args) + { + UNIMPLEMENTED ("initialise path array components"); + } + + // standard copy operations acceptable + + + size_t + size() const + { + UNIMPLEMENTED ("path implementation storage"); + } + + bool + empty() const + { + UNIMPLEMENTED ("path implementation storage"); + } + + operator string() const; + + + Literal + operator[] (size_t idx) + { + UNIMPLEMENTED ("path implementation storage"); + } + + + protected: /* ==== Iteration control API for IterAdapter ==== */ + + /** Implementation of Iteration-logic: pull next element. */ + friend void + iterNext (const PathArray* src, Literal* pos) + { + ++pos; + checkPoint (src,pos); + } + + /** Implementation of Iteration-logic: detect iteration end. */ + friend bool + checkPoint (const PathArray* src, Literal* pos) + { + REQUIRE (src); + if ((pos != nullptr) && (pos != src->storage_end())) + return true; + else + { + pos = nullptr; + return false; + } } + + public: + using iterator = lib::IterAdapter; + using const_iterator = iterator; + + iterator begin() const { UNIMPLEMENTED ("content iteration"); } + iterator end() const { UNIMPLEMENTED ("content iteration"); } + + friend iterator begin(PathArray const& pa) { return pa.begin();} + friend iterator end (PathArray const& pa) { return pa.end(); } + + private: + Literal* + storage_end() const + { + UNIMPLEMENTED ("path implementation storage"); + } + }; + + + inline + PathArray::operator string() const + { + if (this->empty()) return ""; + + string buff; + size_t expectedLen = this->size() * 10; + buff.reserve (expectedLen); + for (Literal elm : *this) + buff += elm + "/"; + + // chop off last delimiter + size_t len = buff.length(); + ASSERT (len >= 1); + buff.resize(len-1); + return buff; + } + + + +}// namespace lib +#endif /*LIB_PATH_ARRAY_H*/ diff --git a/tests/15library.tests b/tests/15library.tests index 5131419cc..fd393be54 100644 --- a/tests/15library.tests +++ b/tests/15library.tests @@ -415,6 +415,11 @@ return: 0 END +TEST "path array abstraction" PathArray_test < + + 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 path-array-test.cpp + ** unit test \ref PathArray_test + */ + + +#include "lib/test/run.hpp" +#include "lib/test/test-helper.hpp" +#include "lib/path-array.hpp" +//#include "lib/format-cout.hpp" +#include "lib/format-util.hpp" +//#include "lib/idi/entry-id.hpp" +//#include "lib/diff/gen-node.hpp" +#include "lib/util.hpp" + +#include + + +using std::string; +//using lib::idi::EntryID; +//using lib::diff::GenNode; +//using util::isSameObject; +using util::isnil; +using util::join; + + + +namespace lib { +namespace test { + +// using lumiera::error::LUMIERA_ERROR_WRONG_TYPE; + using lumiera::error::LUMIERA_ERROR_INDEX_BOUNDS; + using lumiera::error::LUMIERA_ERROR_LOGIC; + + namespace { //Test fixture... + + }//(End)Test fixture + + + /******************************************************************************//** + * @test verify abstraction wrapper to handle some char pointers in the way of a + * standard sequence container with iteration and range checks. + * + * @see path-array.hpp + * @see UICoord_test + * @see Navigator + */ + class PathArray_test : public Test + { + + virtual void + run (Arg) + { + verify_basics(); + verify_iteration(); + verify_comparisons(); + } + + + void + verify_basics() + { + PathArray undef; + CHECK (isnil (undef)); + + PathArray parr{"Γ","Δ","Θ","Ξ","Σ","Ψ","Φ","Ω"}; + CHECK (not isnil (parr)); + CHECK (8 == parr.size()); + + // indexed access + CHECK ("Γ" == parr[0]); + CHECK ("Δ" == parr[1]); + CHECK ("Θ" == parr[2]); + CHECK ("Ξ" == parr[3]); + CHECK ("Σ" == parr[4]); + CHECK ("Ψ" == parr[5]); + CHECK ("Φ" == parr[6]); + CHECK ("Ω" == parr[7]); + + VERIFY_ERROR (INDEX_BOUNDS, parr[8]); + + // string representation + CHECK ("Γ/Δ/Θ/Ξ/Σ/Ψ/Φ/Ω" == string(parr)); + + // new value can be assigned, but not altered in place + parr = PathArray{nullptr,nullptr,"Θ",nullptr,nullptr,nullptr,"Φ"}; + CHECK (7 == parr.size()); + + // representation is trimmed and filled + CHECK ("Θ/*/*/*/Φ" == string(parr)); + CHECK (NULL == parr[0]); + CHECK (NULL == parr[1]); + CHECK ("Θ" == parr[2]); + CHECK ("*" == parr[3]); + CHECK ("*" == parr[4]); + CHECK ("*" == parr[5]); + CHECK ("Φ" == parr[6]); + VERIFY_ERROR (INDEX_BOUNDS, parr[7]); + VERIFY_ERROR (INDEX_BOUNDS, parr[8]); + } + + + void + verify_iteration() + { + PathArray parr; + CHECK (isnil (parr)); + // path is iterable + CHECK ("" == join(parr)); + + parr = PathArray{"Γ","Δ","Θ","Ξ","Σ","Ψ","Φ","Ω"}; + CHECK (8 == parr.size()); + // path is iterable + CHECK ("ΓΔΘΞΣΨΦΩ" == join(parr,"")); + + // iteration matches index order + uint i=0; + for (PathArray::iterator ii = parr.begin(); ii; ++ii, ++i) + CHECK (parr[i] == *ii); + CHECK (8 == i); + + + // path information is automatically trimmed and filled + parr = PathArray{nullptr,nullptr,"Θ",nullptr,nullptr,nullptr,"Φ"}; + CHECK (7 == parr.size()); + CHECK ("Θ***Φ" == join(parr,"")); + + parr = PathArray{nullptr,"Δ",nullptr,"Ξ",nullptr,nullptr,"Φ"}; + CHECK (4 == parr.size()); + CHECK ("Δ*Ξ" == join(parr,"")); + + parr = PathArray{nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,"Ω",nullptr}; + CHECK (16 == parr.size()); + CHECK ("Ω" == join(parr,"")); + + // index numbering starts at absolute root + CHECK ("Ω" == *parr.begin()); + CHECK (nullptr == parr[0]); + CHECK ("Ω" == parr[15]); + VERIFY_ERROR (INDEX_BOUNDS, parr[16]); + } + + + void + verify_comparisons() + { + UNIMPLEMENTED ("verify comparison of UI coordinates"); + } + }; + + + /** Register this test class... */ + LAUNCHER (PathArray_test, "unit gui"); + + +}} // namespace lib::test