diff --git a/src/lib/diff/gen-node.cpp b/src/lib/diff/gen-node.cpp index e3c7f28d6..8806cd1f4 100644 --- a/src/lib/diff/gen-node.cpp +++ b/src/lib/diff/gen-node.cpp @@ -50,8 +50,10 @@ #include +using util::join; using boost::lexical_cast; using lib::time::TimeValue; +using lib::transformIterator; using util::almostEqual; using lib::hash::LuidH; @@ -290,4 +292,70 @@ namespace diff{ } + + + + /** compact textual representation of a Record (»object«). */ + string renderCompact (Rec const& rec) + { + auto renderChild = [](diff::GenNode const& n){ return renderCompact(n); }; + auto renderAttrib = [](diff::GenNode const& n){ + return (n.isNamed()? n.idi.getSym()+"=" : "") + + renderCompact(n); + }; + + return (Rec::TYPE_NIL==rec.getType()? "" : rec.getType()) + + "{" + + join (transformIterator (rec.attribs(), renderAttrib)) + + (isnil(rec.scope())? "" : "|") + + join (transformIterator (rec.scope() , renderChild)) + + "}" + ; + } + + string + renderCompact (RecRef const& ref) + { + return "Ref->" + (ref.empty()? util::BOTTOM_INDICATOR + : renderCompact (*ref.get())); + } + + /** @remark presentation is oriented towards readability + * - numbers are slightly rounded (see \ref util::showDouble() ) + * - time values are displayed timecode-like + * - nested scopes are displayed recursively, enclosed in curly brackets + * @see text-template-gen-node-binding.hpp + */ + string + renderCompact (GenNode const& node) + { + class Renderer + : public Variant::Renderer + { + #define RENDER_CONTENT(_TY_) \ + virtual string handle (_TY_ const& val) override { return util::toString(val); } + + RENDER_CONTENT (int) + RENDER_CONTENT (int64_t) + RENDER_CONTENT (short) + RENDER_CONTENT (char) + RENDER_CONTENT (double) + RENDER_CONTENT (bool) + RENDER_CONTENT (time::Time) + RENDER_CONTENT (time::Offset) + RENDER_CONTENT (time::Duration) + RENDER_CONTENT (time::TimeSpan) + #undef RENDER_CONTENT + + virtual string handle (string const& val) override { return val; } + virtual string handle (LuidH const& val) override { return util::showHash(val, 2);} + virtual string handle (RecRef const& ref) override { return renderCompact(ref); } + virtual string handle (Rec const& rec) override { return renderCompact(rec); } + }; + + Renderer visitor; + return node.data.accept (visitor); + } + + }} // namespace lib::diff diff --git a/src/lib/diff/gen-node.hpp b/src/lib/diff/gen-node.hpp index 696f988b5..649b82afd 100644 --- a/src/lib/diff/gen-node.hpp +++ b/src/lib/diff/gen-node.hpp @@ -501,6 +501,15 @@ namespace diff{ }; + /** compact textual representation of a GenNode tree */ + string renderCompact (GenNode const&); + string renderCompact (RecRef const&); + string renderCompact (Rec const&); + + + + + /** * metafunction to detect types able to be wrapped into a GenNode. diff --git a/src/lib/diff/record.hpp b/src/lib/diff/record.hpp index b51a4bd66..e735cdb10 100644 --- a/src/lib/diff/record.hpp +++ b/src/lib/diff/record.hpp @@ -683,6 +683,12 @@ namespace diff{ return record_; } + operator string() const + { + return "Ref->" + (empty()? util::BOTTOM_INDICATOR + : string(*record_)); + } + /** @note equality of references (instance pointers), not targets */ friend bool operator== (RecordRef const& r1, RecordRef const& r2) diff --git a/src/lib/variant.hpp b/src/lib/variant.hpp index db24b9cd3..e5ae019d0 100644 --- a/src/lib/variant.hpp +++ b/src/lib/variant.hpp @@ -252,6 +252,13 @@ namespace lib { virtual ~Predicate() { } ///< this is an interface }; + class Renderer + : public VisitorConstFunc + { + public: + virtual ~Renderer() { } ///< this is an interface + }; ///////////////////////////////////TICKET #1361 : unable to make the Visitor fully generic + /** * Metafunction to pick the first of the variant's types, * which satisfies the given trait or predicate template @@ -274,9 +281,10 @@ namespace lib { virtual ~Buffer() {} ///< this is an ABC with VTable - virtual void dispatch (Visitor&) =0; - virtual bool dispatch (Predicate&) const =0; - virtual operator string() const =0; + virtual void dispatch (Visitor&) =0; + virtual bool dispatch (Predicate&) const =0; + virtual string dispatch (Renderer&) const =0; + virtual operator string() const =0; }; @@ -379,6 +387,15 @@ namespace lib { return typeDispatcher.handle (this->access()); } + string + dispatch (Renderer& visitor) const + { + using Dispatcher = variant::VFunc::template ValueAcceptInterface; + + Dispatcher& typeDispatcher = visitor; + return typeDispatcher.handle (this->access()); + } + /** diagnostic helper */ operator string() const; }; @@ -536,6 +553,12 @@ namespace lib { { return buffer().dispatch (visitor); } + + string + accept (Renderer& visitor) const + { + return buffer().dispatch (visitor); + } }; diff --git a/tests/library/diff/gen-node-test.cpp b/tests/library/diff/gen-node-test.cpp index 12d732b4a..2feeed313 100644 --- a/tests/library/diff/gen-node-test.cpp +++ b/tests/library/diff/gen-node-test.cpp @@ -147,6 +147,8 @@ namespace test{ CHECK (!n3.isNamed()); cout << n3 <