diff --git a/src/lib/diff/test-mutation-target.hpp b/src/lib/diff/test-mutation-target.hpp index 762a1a4d2..d5cd1feb4 100644 --- a/src/lib/diff/test-mutation-target.hpp +++ b/src/lib/diff/test-mutation-target.hpp @@ -395,6 +395,24 @@ namespace diff{ } } + /** locate element already accepted into the taget sequence + * and assigne the designated payload value to it. */ + virtual bool + assignElm (GenNode const& spec) + { + UNIMPLEMENTED("locate and assign"); + return false; + } + + /** locate the designated target element and build a suittable + * sub-mutator for this element into the provided target buffer */ + virtual bool + mutateChild (GenNode const& spec, TreeMutator::MutatorBuffer targetBuff) + { + UNIMPLEMENTED("locate and open sub mutator"); + return false; + } + TestWireTap(Target& dummy, PAR const& chain) : PAR(chain) diff --git a/src/lib/diff/tree-diff-mutator-binding.hpp b/src/lib/diff/tree-diff-mutator-binding.hpp index adc2669e6..f32c3f972 100644 --- a/src/lib/diff/tree-diff-mutator-binding.hpp +++ b/src/lib/diff/tree-diff-mutator-binding.hpp @@ -327,19 +327,19 @@ namespace diff{ } void - locate_and_assign (GenNode const& n) + assignElm (GenNode const& n) { UNIMPLEMENTED("locate allready accepted element and assign given new payload"); } void - locate_and_openSubScope (GenNode const& n) + open_subScope (GenNode const& n) { UNIMPLEMENTED("locate allready accepted element and open recursive sub-scope for mutation"); } void - closeSubScope() + close_subScope() { UNIMPLEMENTED("finish and leave sub scope and return to invoking parent scope"); } @@ -401,14 +401,14 @@ namespace diff{ virtual void set (GenNode const& n) override { - locate_and_assign (n); + assignElm (n); } /** open nested scope to apply diff to child object */ virtual void mut (GenNode const& n) override { - locate_and_openSubScope (n); + open_subScope (n); Rec const& childRecord = child.data.get(); TRACE (diff, "tree-diff: ENTER scope %s", cStr(childRecord)); @@ -421,7 +421,7 @@ namespace diff{ TRACE (diff, "tree-diff: LEAVE scope %s", cStr(describeScope())); __expect_end_of_scope (n.idi); - closeSubScope(); + close_subScope(); __expect_valid_parent_scope (n.idi); } diff --git a/src/lib/diff/tree-mutator.hpp b/src/lib/diff/tree-mutator.hpp index 22e0969f8..204edd04d 100644 --- a/src/lib/diff/tree-mutator.hpp +++ b/src/lib/diff/tree-mutator.hpp @@ -72,16 +72,67 @@ #include "lib/error.hpp" #include "lib/symbol.hpp" #include "lib/diff/gen-node.hpp" +#include "lib/opaque-holder.hpp" //#include "lib/util.hpp" //#include "lib/format-string.hpp" #include +#include ////TODO #include //#include //#include namespace lib { + /////////////////////////////TODO move over into opaque-holder.hpp + /** + * handle to allow for safe _»remote implantation«_ + * of an unknown subclass into a given OpaqueHolder buffer, + * without having to disclose the concrete buffer type or size. + * @remarks this is especially geared towards use in APIs, allowing + * a not yet known implementation to implant an agent or collaboration + * partner into the likewise undisclosed innards of the exposed service. + * @warning the type BA must expose a virtual dtor, since the targetted + * OpaqueHolder has to take ownership of the implanted object. + */ + template + class PlantingHandle + { + void* buffer_; + size_t maxSiz_; + + ///////TODO static assert to virtual dtor?? + public: + template + PlantingHandle (OpaqueHolder& targetBuffer) + : buffer_(&targetBuffer) + , maxSiz_(maxSiz_) + { } + + + template + BA& + create (ARGS&& ...args) + { + if (sizeof(SUB) > maxSiz_) + throw error::Fatal("Unable to implant implementation object of size " + "exceeding the pre-established storage buffer capacity." + ,error::LUMIERA_ERROR_CAPACITY); + + using Holder = OpaqueHolder; + Holder& holder = *static_cast (buffer_); + + return holder.create (std::forward (args)...); + } + + template + bool + canCreate() const + { + return sizeof(SUB) <= maxSiz_; + } + }; + /////////////////////////////TODO move over into opaque-holder.hpp namespace diff{ namespace error = lumiera::error; @@ -92,6 +143,8 @@ namespace diff{ using std::string; + + class TestMutationTarget; // for unit testing @@ -166,10 +219,31 @@ namespace diff{ return false; } - virtual TreeMutator& - mutateChild (ID id) + /** locate the designated target element + * (must be already accepted into the target sequence). + * Perform an assignement with the given payload value + * @throw when assignement fails (typically error::Logic) + * @return false when unable to locate the target */ + virtual bool + assignElm (GenNode const&) { - UNIMPLEMENTED("expose a recursive TreeMutator to transform the denoted child"); + // do nothing by default + return false; + } + + + using MutatorBuffer = PlantingHandle; + + /** locate the designated target element + * and build a suittable sub-mutator for this element + * into the provided target buffer + * @throw error::Fatal when buffer is insufficient + * @return false when unable to locate the target */ + virtual bool + mutateChild (GenNode const&, MutatorBuffer) + { + // do nothing by default + return false; } virtual void setAttribute (ID, Attribute&) { /* do nothing by default */ } diff --git a/src/lib/opaque-holder.hpp b/src/lib/opaque-holder.hpp index 4528c8240..750f39483 100644 --- a/src/lib/opaque-holder.hpp +++ b/src/lib/opaque-holder.hpp @@ -490,7 +490,7 @@ namespace lib { * The whole compound is copyable if and only if the contained * object is copyable. * - * \par using OpaqueHolder + * ## using OpaqueHolder * OpaqueHolder instances are copyable value objects. They are created * either empty, by copy from an existing OpaqueHolder, or by directly * specifying the concrete object to embed. This target object will be @@ -500,16 +500,19 @@ namespace lib { * Later on, the embedded value might be accessed * - using the smart-ptr-like access through the common base interface BA * - when knowing the exact type to access, the templated #get might be an option - * - the empty state of the container and a \c isValid() on the target may be checked - * - a combination of both is available as a \c bool check on the OpaqueHolder instance. + * - the empty state of the container and a `isValid()` on the target may be checked + * - a combination of both is available as a `bool` check on the OpaqueHolder instance. * - * For using OpaqueHolder, several \b assumptions need to be fulfilled + * For using OpaqueHolder, several *assumptions* need to be fulfilled * - any instance placed into OpaqueHolder is below the specified maximum size * - the caller cares for thread safety. No concurrent get calls while in mutation! + * + * @tparam BA the nominal Base/Interface class for a family of types + * @tparam siz maximum storage required for the targets to be held inline */ template - < class BA ///< the nominal Base/Interface class for a family of types - , size_t siz = sizeof(BA) ///< maximum storage required for the targets to be held inline + < class BA + , size_t siz = sizeof(BA) > class OpaqueHolder : public InPlaceAnyHolder > @@ -568,11 +571,15 @@ namespace lib { * and especially it is mandatory for the base class to provide a * virtual dtor. On the other hand, just the (alignment rounded) * storage for the object(s) placed into the buffer is required. + * + * @tparam BA the nominal Base/Interface class for a family of types + * @tparam siz maximum storage required for the targets to be held inline + * @tparam DEFAULT the default instance to place initially */ template - < class BA ///< the nominal Base/Interface class for a family of types - , size_t siz = sizeof(BA) ///< maximum storage required for the targets to be held inline - , class DEFAULT = BA ///< the default instance to place initially + < class BA + , size_t siz = sizeof(BA) + , class DEFAULT = BA > class InPlaceBuffer : boost::noncopyable diff --git a/src/lib/scoped-collection.hpp b/src/lib/scoped-collection.hpp index 261707ba7..6de7e52a6 100644 --- a/src/lib/scoped-collection.hpp +++ b/src/lib/scoped-collection.hpp @@ -43,7 +43,7 @@ ** number of objects is (heap) allocated right away, but no objects are ** created. Later on, individual objects are "pushed" into the collection ** by invoking #appendNewElement() to create a new element of the default - ** type I) or #appendNew(args) to create some subtype. This way, + ** type `I`) or #appendNew(args) to create some subtype. This way, ** the container is being filled successively. ** - the "RAII style" usage strives to create all of the content objects ** right away, immediately after the memory allocation. This usage pattern @@ -53,7 +53,7 @@ ** @note intentionally there is no operation to discard individual objects, ** all you can do is to #clear() the whole container. ** @note the container can hold instances of a subclass of the type defined - ** by the template parameter I. But you need to ensure in this case + ** by the template parameter `I`. But you need to ensure in this case ** that the defined buffer size for each element (2nt template parameter) ** is sufficient to hold any of these subclass instances. This condition ** is protected by a static assertion (compilation failure). @@ -93,10 +93,12 @@ namespace lib { * All child objects reside in a common chunk of storage * and are owned and managed by this collection holder. * Array style access and iteration is provided. + * @tparam I the nominal Base/Interface class for a family of types + * @tparam siz maximum storage required for the targets to be held inline */ template - < class I ///< the nominal Base/Interface class for a family of types - , size_t siz = sizeof(I) ///< maximum storage required for the targets to be held inline + < class I + , size_t siz = sizeof(I) > class ScopedCollection : boost::noncopyable diff --git a/src/lib/scoped-holder.hpp b/src/lib/scoped-holder.hpp index 53cbd3ec3..379a3f802 100644 --- a/src/lib/scoped-holder.hpp +++ b/src/lib/scoped-holder.hpp @@ -44,7 +44,9 @@ ** supporting dynamic growth (like in std::vector#resize() ) additionally ** requires a facility to transfer the lifecycle management control between ** holder instances. This is the purpose of the \c transfer_control - ** friend function. + ** friend function. + ** + ** @deprecated this is a pre C++11 concept and superseded by rvalue references ** ** @see scoped-holder-test.cpp ** @see scoped-holder-transfer.hpp use in std::vector diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 54adebcef..0ed431b46 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -899,39 +899,102 @@ - + + - + + - - - + + + + - - - - - + - + - - + + + + + + + + + + + + + + +

+ throw when +

+

+ insufficent space +

+ + +
- + + - - - + + + + + + + +

+ invoke buildMutator +

+ + +
+
+ + +
- + - + + + + + + + +

+ NOTE: mutator need to be written in such a way +

+

+ to be just discarded when done with the alterations. +

+

+ That is, the mutator must not incorporate the target data, rather it is expected +

+

+ to construct the new target data efficiently in place. +

+ + +
+ +
+ + + + +
@@ -1771,6 +1834,13 @@
+ + + + + + +