UI-Coordinates: implement path split and appending of multiple components
Unit test passes thus far
This commit is contained in:
parent
835b964e63
commit
286b1829fe
4 changed files with 113 additions and 37 deletions
|
|
@ -57,7 +57,9 @@
|
|||
#include "lib/util.hpp"
|
||||
|
||||
//#include <boost/noncopyable.hpp>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
//#include <memory>
|
||||
|
||||
|
|
@ -134,7 +136,7 @@ namespace interact {
|
|||
|
||||
// convenience shortcuts to start mutation on a copy...
|
||||
|
||||
Builder path (string pathDefinition) const;
|
||||
Builder path (Literal pathDefinition) const;
|
||||
Builder append (Literal elmID) const;
|
||||
Builder prepend (Literal elmID) const;
|
||||
|
||||
|
|
@ -257,6 +259,13 @@ namespace interact {
|
|||
/** @note Builder allowed to manipulate stored data */
|
||||
friend class Builder;
|
||||
|
||||
size_t
|
||||
findStartIdx() const
|
||||
{
|
||||
REQUIRE (not empty());
|
||||
return indexOf (*begin());
|
||||
}
|
||||
|
||||
Literal
|
||||
accesComponent (UIPathElm idx) const
|
||||
{
|
||||
|
|
@ -267,15 +276,68 @@ namespace interact {
|
|||
void
|
||||
setComponent (size_t idx, Literal newContent)
|
||||
{
|
||||
Literal* storage = maybeExpandTo (idx);
|
||||
Literal* storage = expandPosition (idx);
|
||||
setContent (storage, newContent);
|
||||
}
|
||||
|
||||
size_t
|
||||
findStartIdx() const
|
||||
|
||||
/** replace / overwrite existing content starting at given index.
|
||||
* @param idx where to start adding content; storage will be expanded to accommodate
|
||||
* @param newContent either a single element, or several elements delimited by `'/'`
|
||||
* @note - a path sequence will be split at `'/'` and the components _interned_
|
||||
* - any excess elements will be cleared
|
||||
* @warning need to invoke PathArray::normalise() afterwards
|
||||
*/
|
||||
void
|
||||
setTailSequence (size_t idx, Literal newContent)
|
||||
{
|
||||
REQUIRE (not empty());
|
||||
return indexOf (*begin());
|
||||
std::vector<Literal> elms;
|
||||
if (not isnil (newContent))
|
||||
{
|
||||
if (not std::strchr (newContent, '/'))
|
||||
{
|
||||
// single element: just place it as-is
|
||||
// and remove any further content behind
|
||||
elms.emplace_back (newContent);
|
||||
}
|
||||
else
|
||||
{ // it is actually a sequence of elements,
|
||||
// which need to be split first, and then
|
||||
// interned into the global symbol table
|
||||
string sequence{newContent};
|
||||
size_t pos = 0;
|
||||
size_t last = 0;
|
||||
while (string::npos != (last = sequence.find ('/', pos)))
|
||||
{
|
||||
elms.emplace_back (Symbol{sequence.substr(pos, last - pos)});
|
||||
pos = last + 1;
|
||||
}
|
||||
sequence = sequence.substr(pos);
|
||||
if (not isnil (sequence))
|
||||
elms.emplace_back (Symbol{sequence});
|
||||
} }
|
||||
|
||||
setTailSequence (idx, elms);
|
||||
}
|
||||
|
||||
/** replace the existing path information with the given elements
|
||||
* @note - storage will possibly be expanded to accommodate
|
||||
* - the individual path elements will be _interned_ as Symbol
|
||||
* - any excess elements will be cleared
|
||||
* - the pathElms can be _empty_ in which case just
|
||||
* any content starting from `idx` will be cleared
|
||||
* @warning need to invoke PathArray::normalise() afterwards
|
||||
*/
|
||||
void
|
||||
setTailSequence (size_t idx, std::vector<Literal>& pathElms)
|
||||
{
|
||||
size_t cnt = pathElms.size();
|
||||
expandPosition (idx + cnt);
|
||||
for (size_t i=0 ; i < cnt; ++i)
|
||||
setContent (expandPosition(idx + i), pathElms[i]);
|
||||
size_t end = size();
|
||||
for (size_t i = idx+cnt; i<end; ++i)
|
||||
setContent (expandPosition(i), nullptr);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -361,11 +423,15 @@ namespace interact {
|
|||
}
|
||||
|
||||
|
||||
/** augment UI coordinates by appending a further component at the end */
|
||||
/** augment UI coordinates by appending a further component at the end.
|
||||
* @note the element might define a sequence of components separated by `'/'`,
|
||||
* in which case several elements will be appended.
|
||||
*/
|
||||
Builder
|
||||
append (Literal elmID)
|
||||
append (Literal elm)
|
||||
{
|
||||
uic_.setComponent (uic_.size(), elmID);
|
||||
if (not isnil(elm))
|
||||
uic_.setTailSequence (uic_.size(), elm);
|
||||
return std::move (*this);
|
||||
}
|
||||
|
||||
|
|
@ -381,11 +447,16 @@ namespace interact {
|
|||
return std::move (*this);
|
||||
}
|
||||
|
||||
/** augment UI coordinates to define a complete local path */
|
||||
/**
|
||||
* augment UI coordinates to define a complete local path
|
||||
* @param pathDef a path, possibly with multiple components separated by `'/'`
|
||||
* @note any existing path definition is completely replaced by the new path
|
||||
*/
|
||||
Builder
|
||||
path (string pathDefinition)
|
||||
path (Literal pathDef)
|
||||
{
|
||||
UNIMPLEMENTED ("set path");
|
||||
uic_.setTailSequence (UIC_PART, pathDef);
|
||||
return std::move (*this);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -448,7 +519,7 @@ namespace interact {
|
|||
* resulting components will be stored/retrieved as Symbol
|
||||
*/
|
||||
inline UICoord::Builder
|
||||
UICoord::path (string pathDefinition) const
|
||||
UICoord::path (Literal pathDefinition) const
|
||||
{
|
||||
return Builder(*this).path (pathDefinition);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -201,14 +201,19 @@ namespace lib {
|
|||
resizeTo (size_t cnt)
|
||||
{
|
||||
if (cnt > size())
|
||||
{ // copy to expanded storage
|
||||
auto target = new const char* [cnt+1];
|
||||
auto pos = std::copy (storage_, storage_+1+size(), target);
|
||||
for ( ; pos < target+1+cnt; ++pos)
|
||||
*pos = nullptr;
|
||||
{ // need more storage
|
||||
if (storage_)
|
||||
delete[] storage_;
|
||||
storage_ = reinterpret_cast<PStorage> (target);
|
||||
{ // copy content to new expanded storage
|
||||
auto target = new const char* [cnt+1];
|
||||
auto pos = std::copy (storage_, storage_+1+size(), target);
|
||||
for ( ; pos < target+1+cnt; ++pos)
|
||||
*pos = nullptr;
|
||||
delete[] storage_;
|
||||
storage_ = reinterpret_cast<PStorage> (target);
|
||||
}
|
||||
else // allocate and init empty
|
||||
storage_ = new Literal [cnt+1];
|
||||
|
||||
size (storage_) = cnt;
|
||||
return;
|
||||
}
|
||||
|
|
@ -453,7 +458,7 @@ namespace lib {
|
|||
* @return pointer to the storage, either existing or reallocated
|
||||
*/
|
||||
Literal*
|
||||
maybeExpandTo (size_t idx)
|
||||
expandPosition (size_t idx)
|
||||
{
|
||||
if (chunk_size <= idx and size() <= idx)
|
||||
tail_.resizeTo(idx+1 - chunk_size);
|
||||
|
|
|
|||
|
|
@ -275,23 +275,23 @@ namespace test {
|
|||
CHECK ("α/β/γ/δ/ε/λ/ον" == uic.getPath());
|
||||
|
||||
uic = uic.prepend("perspective");
|
||||
CHECK ("UI:UI:?[perspective]-panel.*. /α/β/γ/δ/ε/λ/ον" == string(uic));
|
||||
CHECK ("UI:?[perspective]-panel.*. /α/β/γ/δ/ε/λ/ον" == string(uic));
|
||||
CHECK ("?[perspective]-panel.*. " == uic.getComp());
|
||||
CHECK ("α/β/γ/δ/ε/λ/ον" == uic.getPath());
|
||||
|
||||
uic = uic.prepend("win");
|
||||
CHECK ("UI:UI:win[perspective]-panel.*. /α/β/γ/δ/ε/λ/ον" == string(uic));
|
||||
CHECK ("UI:win[perspective]-panel.*. /α/β/γ/δ/ε/λ/ον" == string(uic));
|
||||
CHECK ("win[perspective]-panel.*. " == uic.getComp());
|
||||
CHECK ("α/β/γ/δ/ε/λ/ον" == uic.getPath());
|
||||
|
||||
uic = uic.persp("");
|
||||
CHECK ("UI:UI:win[*]-panel.*. /α/β/γ/δ/ε/λ/ον" == string(uic));
|
||||
CHECK ("UI:win[*]-panel.*. /α/β/γ/δ/ε/λ/ον" == string(uic));
|
||||
CHECK ("win[*]-panel.*. " == uic.getComp());
|
||||
CHECK ("α/β/γ/δ/ε/λ/ον" == uic.getPath());
|
||||
CHECK (12 == uic.size());
|
||||
|
||||
uic = uic.path(" ");
|
||||
CHECK ("UI:UI:win[*]-panel.*. / " == string(uic));
|
||||
CHECK ("UI:win[*]-panel.*. / " == string(uic));
|
||||
CHECK ("win[*]-panel.*. " == uic.getComp());
|
||||
CHECK (" " == uic.getPath());
|
||||
CHECK (6 == uic.size());
|
||||
|
|
@ -299,39 +299,39 @@ namespace test {
|
|||
VERIFY_ERROR (INDEX_BOUNDS, uic[UIC_PART+1]);
|
||||
|
||||
uic = uic.path(nullptr);
|
||||
CHECK ("UI:UI:win[*]-panel.*. " == string(uic));
|
||||
CHECK ("UI:win[*]-panel.*. " == string(uic));
|
||||
CHECK ("win[*]-panel.*. " == uic.getComp());
|
||||
CHECK ("" == uic.getPath());
|
||||
CHECK (5 == uic.size());
|
||||
VERIFY_ERROR (INDEX_BOUNDS, uic[UIC_PART]);
|
||||
|
||||
uic = uic.append(nullptr);
|
||||
CHECK ("UI:UI:win[*]-panel.*. " == string(uic));
|
||||
CHECK ("UI:win[*]-panel.*. " == string(uic));
|
||||
CHECK ("win[*]-panel.*. " == uic.getComp());
|
||||
CHECK ("" == uic.getPath());
|
||||
CHECK (5 == uic.size());
|
||||
|
||||
uic = uic.append("*");
|
||||
CHECK ("UI:UI:win[*]-panel.*. " == string(uic));
|
||||
CHECK ("UI:win[*]-panel.*. " == string(uic));
|
||||
CHECK ("win[*]-panel.*. " == uic.getComp());
|
||||
CHECK ("" == uic.getPath());
|
||||
CHECK (5 == uic.size());
|
||||
|
||||
uic = uic.append("**");
|
||||
CHECK ("UI:UI:win[*]-panel.*. /**" == string(uic));
|
||||
CHECK ("UI:win[*]-panel.*. /**" == string(uic));
|
||||
CHECK ("win[*]-panel.*. " == uic.getComp());
|
||||
CHECK ("**" == uic.getPath());
|
||||
CHECK ("**" == uic[UIC_PART]);
|
||||
CHECK (6 == uic.size());
|
||||
|
||||
uic = uic.tab("");
|
||||
CHECK ("UI:UI:win[*]-panel.*.*/**" == string(uic));
|
||||
CHECK ("UI:win[*]-panel.*.*/**" == string(uic));
|
||||
CHECK ("win[*]-panel.*.*" == uic.getComp());
|
||||
CHECK ("**" == uic.getPath());
|
||||
CHECK (6 == uic.size());
|
||||
|
||||
uic = uic.path("");
|
||||
CHECK ("UI:UI:win[*]-panel" == string(uic));
|
||||
CHECK ("UI:win[*]-panel" == string(uic));
|
||||
CHECK ("win[*]-panel" == uic.getComp());
|
||||
CHECK ("" == uic.getPath());
|
||||
CHECK (3 == uic.size());
|
||||
|
|
|
|||
|
|
@ -3914,13 +3914,13 @@
|
|||
<node COLOR="#338800" CREATED="1506887647152" ID="ID_1069521621" MODIFIED="1506887654873" TEXT="String representation">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1506906671372" ID="ID_458222870" MODIFIED="1506906680445" TEXT="Builder">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1506906671372" ID="ID_458222870" MODIFIED="1506919618620" TEXT="Builder">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1506906657270" ID="ID_1234040290" MODIFIED="1506906687339" TEXT="builder functions">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1506906664501" ID="ID_1257993809" MODIFIED="1506906689283" TEXT="mutator functions">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1506906664501" ID="ID_1257993809" MODIFIED="1506919612697" TEXT="mutator functions">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1506181727069" ID="ID_467120404" MODIFIED="1506181737140" TEXT="lokale Prädikate">
|
||||
|
|
@ -3976,8 +3976,8 @@
|
|||
<node COLOR="#338800" CREATED="1506182009518" ID="ID_138248232" MODIFIED="1506906630089" TEXT="verify_basics">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1506182009519" ID="ID_1637725534" MODIFIED="1506906649946" TEXT="verify_builder">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1506182009519" ID="ID_1637725534" MODIFIED="1506919626951" TEXT="verify_builder">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1506182009519" ID="ID_542761230" MODIFIED="1506182101802" TEXT="verify_comparisons">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue