WIP: decision about the builder sequence
after sleeping a night over this, it seems obvios that we do not want to start the build proces "implicitly", starting from a Record<GenNode>. Rather, we always want the user to plant a dedicated Mutator object, which then can remain noncopyable and is passed by reference through the whole builder chain. Movin innards of *this object* are moved away a the end of the chain does not pose much risk.
This commit is contained in:
parent
d92878876a
commit
d14c502ea9
3 changed files with 35 additions and 55 deletions
|
|
@ -123,6 +123,7 @@ namespace diff{
|
||||||
class GenNode;
|
class GenNode;
|
||||||
|
|
||||||
using Rec = Record<GenNode>;
|
using Rec = Record<GenNode>;
|
||||||
|
using MakeRec = Rec::Mutator;
|
||||||
using DataValues = meta::Types<int
|
using DataValues = meta::Types<int
|
||||||
,int64_t
|
,int64_t
|
||||||
,short
|
,short
|
||||||
|
|
@ -233,6 +234,19 @@ namespace diff{
|
||||||
return util::startsWith (idi.getSym(), "_CHILD_");
|
return util::startsWith (idi.getSym(), "_CHILD_");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
contains (GenNode const&) const
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED("containment check");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
contains (ID const&) const
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED("containment check by ID");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
friend string
|
friend string
|
||||||
name (GenNode const& node)
|
name (GenNode const& node)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -246,44 +246,6 @@ namespace diff{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ==== extension point for fluent builder API ====== */
|
|
||||||
|
|
||||||
// to initiate and open builder chain:
|
|
||||||
Mutator
|
|
||||||
type (string const& typeID)
|
|
||||||
{
|
|
||||||
return Mutator(*this).type(typeID);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename...ARGS>
|
|
||||||
Mutator
|
|
||||||
attrib (ARGS&& ...args)
|
|
||||||
{
|
|
||||||
return Mutator(*this).attrib(std::forward<ARGS>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename...ARGS>
|
|
||||||
Mutator
|
|
||||||
scope (ARGS&& ...args)
|
|
||||||
{
|
|
||||||
return Mutator(*this).scope(std::forward<ARGS>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
// to close and finish builder chain (needs specialisation)
|
|
||||||
VAL&&
|
|
||||||
genNode()
|
|
||||||
{
|
|
||||||
return Mutator(*this).genNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
VAL&&
|
|
||||||
genNode(string const& symbolicID)
|
|
||||||
{
|
|
||||||
return Mutator(*this).genNode(symbolicID);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ==== Exposing scope and contents for iteration ====== */
|
/* ==== Exposing scope and contents for iteration ====== */
|
||||||
|
|
||||||
using iterator = IterAdapter<typename _Vec::const_iterator, const Record*>;
|
using iterator = IterAdapter<typename _Vec::const_iterator, const Record*>;
|
||||||
|
|
@ -370,6 +332,10 @@ namespace diff{
|
||||||
Rec record_;
|
Rec record_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Mutator()
|
||||||
|
: record_()
|
||||||
|
{ }
|
||||||
|
|
||||||
explicit
|
explicit
|
||||||
Mutator (Rec const& startingPoint)
|
Mutator (Rec const& startingPoint)
|
||||||
: record_(startingPoint)
|
: record_(startingPoint)
|
||||||
|
|
|
||||||
|
|
@ -149,10 +149,10 @@ namespace test{
|
||||||
void
|
void
|
||||||
objectShortcut()
|
objectShortcut()
|
||||||
{
|
{
|
||||||
auto o0 = Rec().genNode();
|
auto o0 = MakeRec().genNode();
|
||||||
auto o1 = Rec().genNode("νόμος");
|
auto o1 = MakeRec().genNode("νόμος");
|
||||||
auto o2 = Rec().type("spam").genNode();
|
auto o2 = MakeRec().type("spam").genNode();
|
||||||
auto o3 = Rec().attrib("Ψ", int64_t(42), "π", 3.14159265358979323846264338328).genNode("νόμος");
|
auto o3 = MakeRec().attrib("Ψ", int64_t(42), "π", 3.14159265358979323846264338328).genNode("λόγος");
|
||||||
|
|
||||||
CHECK (!o0.isNamed());
|
CHECK (!o0.isNamed());
|
||||||
CHECK (isnil(o0.data.get<Rec>()));
|
CHECK (isnil(o0.data.get<Rec>()));
|
||||||
|
|
@ -167,22 +167,22 @@ namespace test{
|
||||||
CHECK (isnil(o2.data.get<Rec>()));
|
CHECK (isnil(o2.data.get<Rec>()));
|
||||||
|
|
||||||
CHECK (o3.isNamed());
|
CHECK (o3.isNamed());
|
||||||
CHECK ("νόμος" == o3.idi.getSym());
|
CHECK ("λόγος" == o3.idi.getSym());
|
||||||
CHECK ("NIL" == o3.data.get<Rec>().getType());
|
CHECK ("NIL" == o3.data.get<Rec>().getType());
|
||||||
CHECK (GenNode("Ψ", int64_t(42)) == o3.data.get<Rec>().get("Ψ"));
|
CHECK (GenNode("Ψ", int64_t(42)) == o3.data.get<Rec>().get("Ψ"));
|
||||||
CHECK (42L == o3.data.get<Rec>().get("Ψ").data.get<int64_t>);
|
CHECK (42L == o3.data.get<Rec>().get("Ψ").data.get<int64_t>());
|
||||||
CHECK (1e-7 > fabs (3.14159265 - o3.data.get<Rec>().get("π").data.get<double>));
|
CHECK (1e-7 > fabs (3.14159265 - o3.data.get<Rec>().get("π").data.get<double>()));
|
||||||
|
|
||||||
LuidH luid;
|
LuidH luid;
|
||||||
//Demonstration: object builder is based on the mutator mechanism for Records...
|
//Demonstration: object builder is based on the mutator mechanism for Records...
|
||||||
auto o4 = Rec::Mutator(o2) // ...use GenNode o2 as starting point
|
auto o4 = Rec::Mutator(o2.data.get<Rec>()) // ...use GenNode o2 as starting point
|
||||||
.appendChild(GenNode("τ", Time(1,2,3,4))) // a named node with Time value
|
.appendChild(GenNode("τ", Time(1,2,3,4))) // a named node with Time value
|
||||||
.scope('*' // a char node
|
.scope('*' // a char node
|
||||||
,"★" // a string node
|
,"★" // a string node
|
||||||
,luid // a hash value (LUID)
|
,luid // a hash value (LUID)
|
||||||
,TimeSpan(Time::ZERO, FSecs(23,25)) // a time span
|
,TimeSpan(Time::ZERO, FSecs(23,25)) // a time span
|
||||||
,Rec().type("ham").scope("eggs").genNode()) // a spam object
|
,MakeRec().type("ham").scope("eggs").genNode()) // a spam object
|
||||||
.genNode("baked beans"); // ---> finish into named node
|
.genNode("baked beans"); // ---> finish into named node
|
||||||
|
|
||||||
CHECK (o4.isNamed());
|
CHECK (o4.isNamed());
|
||||||
CHECK ("baked beans" == o4.idi.getSym());
|
CHECK ("baked beans" == o4.idi.getSym());
|
||||||
|
|
@ -202,7 +202,7 @@ namespace test{
|
||||||
++scope;
|
++scope;
|
||||||
auto spam = *scope;
|
auto spam = *scope;
|
||||||
CHECK (!++scope);
|
CHECK (!++scope);
|
||||||
CHECK ("ham" == spam.getType());
|
CHECK ("ham" == spam.data.get<Rec>().getType());
|
||||||
CHECK (spam.contains (GenNode("eggs")));
|
CHECK (spam.contains (GenNode("eggs")));
|
||||||
|
|
||||||
// but while o4 was based on o2,
|
// but while o4 was based on o2,
|
||||||
|
|
@ -215,7 +215,7 @@ namespace test{
|
||||||
void
|
void
|
||||||
symbolReference()
|
symbolReference()
|
||||||
{
|
{
|
||||||
GenNode ham = Rec().type("spam").attrib("τ", Time(23,42)).genNode("egg bacon sausage and spam");
|
GenNode ham = MakeRec().type("spam").attrib("τ", Time(23,42)).genNode("egg bacon sausage and spam");
|
||||||
|
|
||||||
GenNode::ID hamID(ham);
|
GenNode::ID hamID(ham);
|
||||||
CHECK (hamID == ham.idi);
|
CHECK (hamID == ham.idi);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue