decision how to support tree exploration/reconstruction
initially the intention was to include a "bracketing construct" into the values returned by the iterator. After considering the various implementation and representation approaches, it seems more appropriate just to expose a measure for the depth-in-tree through the iterator itself, leaving any concerns about navigation and structure reconstruction to the usage site. As rationale we consider the full tree reconstruction as a very specialised use case, and as such the normal "just iteration" usage should not pay for this in terms of iterator size and implementation complexity. Once a "level" measure is exposed, the usage site can do precisely the same, with the help of the HierarchyOrientationIndicator.
This commit is contained in:
parent
8e8a67e6df
commit
6da0785d0a
2 changed files with 19 additions and 12 deletions
|
|
@ -428,6 +428,12 @@ namespace diff{
|
||||||
scopes_.emplace_back(n);
|
scopes_.emplace_back(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
depth() const
|
||||||
|
{
|
||||||
|
return scopes_.size();
|
||||||
|
}
|
||||||
|
|
||||||
/* === Iteration control API for IterStateWrapper == */
|
/* === Iteration control API for IterStateWrapper == */
|
||||||
|
|
||||||
friend bool
|
friend bool
|
||||||
|
|
@ -480,6 +486,8 @@ namespace diff{
|
||||||
: IterStateWrapper<const GenNode, ScopeExplorer>
|
: IterStateWrapper<const GenNode, ScopeExplorer>
|
||||||
{
|
{
|
||||||
using IterStateWrapper<const GenNode, ScopeExplorer>::IterStateWrapper;
|
using IterStateWrapper<const GenNode, ScopeExplorer>::IterStateWrapper;
|
||||||
|
|
||||||
|
size_t level() const { return unConst(this)->stateCore().depth(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -285,12 +285,14 @@ namespace test{
|
||||||
|
|
||||||
|
|
||||||
auto iter = n.begin();
|
auto iter = n.begin();
|
||||||
CHECK (!isnil (iter)); // initially the Record itself is exposed
|
CHECK (!isnil (iter));
|
||||||
CHECK ("baked beans" == iter->idi.getSym());
|
CHECK (1 == iter.level());
|
||||||
|
CHECK ("baked beans" == iter->idi.getSym()); // initially the Record itself is exposed
|
||||||
CHECK (Rec::TYPE_NIL == iter->data.get<Rec>().getType());
|
CHECK (Rec::TYPE_NIL == iter->data.get<Rec>().getType());
|
||||||
|
|
||||||
++iter;
|
++iter;
|
||||||
CHECK ("hasSpam" == iter->idi.getSym()); // delve into the contents, starting with the attribute(s)
|
CHECK (2 == iter.level()); // delve into the contents,
|
||||||
|
CHECK ("hasSpam" == iter->idi.getSym()); // ...starting with the attribute(s)
|
||||||
CHECK (true == iter->data.get<bool>());
|
CHECK (true == iter->data.get<bool>());
|
||||||
CHECK ("GenNode-ID(\"hasSpam\")-DataCap|«bool»|1" == string(*iter));
|
CHECK ("GenNode-ID(\"hasSpam\")-DataCap|«bool»|1" == string(*iter));
|
||||||
|
|
||||||
|
|
@ -311,6 +313,7 @@ namespace test{
|
||||||
CHECK ("ham" == iter->data.get<Rec>().getType());
|
CHECK ("ham" == iter->data.get<Rec>().getType());
|
||||||
|
|
||||||
++iter;
|
++iter;
|
||||||
|
CHECK (3 == iter.level());
|
||||||
CHECK ("eggs" == iter->data.get<string>()); // contents of the nested ("spam") object's scope
|
CHECK ("eggs" == iter->data.get<string>()); // contents of the nested ("spam") object's scope
|
||||||
|
|
||||||
++iter;
|
++iter;
|
||||||
|
|
@ -318,20 +321,16 @@ namespace test{
|
||||||
|
|
||||||
++iter;
|
++iter;
|
||||||
CHECK ("spam" == iter->data.get<string>());
|
CHECK ("spam" == iter->data.get<string>());
|
||||||
|
CHECK (3 == iter.level());
|
||||||
|
|
||||||
++iter;
|
++iter;
|
||||||
CHECK ("_END_spam" == iter->idi.getSym()); // bracketing construct to close the nested scope
|
CHECK (2 == iter.level()); // decreasing level indicates we left nested scope
|
||||||
|
|
||||||
++iter;
|
|
||||||
CHECK (!iter->isNamed()); // next item in the enclosing scope
|
CHECK (!iter->isNamed()); // next item in the enclosing scope
|
||||||
CHECK (42 == iter->data.get<int64_t>());
|
CHECK (42 == iter->data.get<int64_t>());
|
||||||
|
CHECK (2 == iter.level());
|
||||||
|
|
||||||
++iter;
|
++iter; // nothing more on top level beyond the initial Record
|
||||||
CHECK ("_END_baked beans" == iter->idi.getSym()); // bracketing returns to top level
|
CHECK (0 == iter.level());
|
||||||
CHECK (isSameObject(n.data.get<Rec>(), iter->data.get<Rec>()));
|
|
||||||
CHECK (Ref(n) == *iter); // actually this is a RecordRef to the original object
|
|
||||||
|
|
||||||
++iter;
|
|
||||||
CHECK (isnil (iter));
|
CHECK (isnil (iter));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue