diff --git a/src/lib/text-template.hpp b/src/lib/text-template.hpp index ba548abd6..3d9bad904 100644 --- a/src/lib/text-template.hpp +++ b/src/lib/text-template.hpp @@ -122,6 +122,7 @@ namespace lib { using StrView = std::string_view; using util::_Fmt; + using util::isnil; using util::unConst; @@ -140,7 +141,7 @@ namespace lib { iterNestedKeys (string key, string const& iterDef) { return explore (util::RegexSearchIter{iterDef, ACCEPT_DATA_ELM}) - .transform ([&](smatch mat){ return key+"."+string{mat[1]}; }); + .transform ([&](smatch mat){ return key+"."+string{mat[1]}+"."; }); } @@ -521,37 +522,75 @@ namespace lib { using MapS = std::map; + /** + * Data-binding for a Map-of-strings. + * Simple keys are retrieved by direct lookup. + * For the representation of nested data sequences, + * the following conventions apply + * - the data sequence itself is represented by an index-key + * - the value associated to this index-key is a CSV sequence + * - each element in this sequence defines a key prefix + * - nested keys are then defined as `..` + * - when key decoration is enabled for a nested data source, each + * lookup for a given key is first tried with the prefix, then as-is. + * Consequently, all data in the sequence must be present in the original + * map, stored under the decorated keys. + * @note multiply nested sequences are _not supported._ + * While it _is_ possible to have nested loops, the resulting sets + * of keys must be disjoint and data must be present in the base map. + * @see TextTemplate_test::verify_Map_binding() + */ template<> struct TextTemplate::DataSource { MapS const * data_; - using Iter = decltype(iterNestedKeys("","")); + string keyPrefix_{}; + + bool isNested() { return not isnil (keyPrefix_); } + bool contains (string key) { - return util::contains (*data_, key); + return (isNested() and util::contains (*data_, keyPrefix_+key)) + or util::contains (*data_, key); } string const& retrieveContent (string key) { - auto elm = data_->find (key); + MapS::const_iterator elm; + if (isNested()) + { + elm = data_->find (keyPrefix_+key); + if (elm == data_->end()) + elm = data_->find (key); + } + else + elm = data_->find (key); ENSURE (elm != data_->end()); return elm->second; } + + using Iter = decltype(iterNestedKeys("","")); + Iter getSequence (string key) { - UNIMPLEMENTED ("extract data sequence from definition key"); + if (not contains(key)) + return Iter{}; + else + return iterNestedKeys (key, retrieveContent(key)); } DataSource openContext (Iter& iter) { REQUIRE (iter); - UNIMPLEMENTED ("open a nested sub-data-ctx based on the given iterator"); + DataSource nested{*this}; + nested.keyPrefix_ = *iter; + return nested; } }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 7637a9f5d..6657732b6 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -112477,11 +112477,11 @@ std::cout << tmpl.render({"what", "World"}) << s - - + + - - + + @@ -112496,8 +112496,8 @@ std::cout << tmpl.render({"what", "World"}) << s - - + + @@ -112505,12 +112505,12 @@ std::cout << tmpl.render({"what", "World"}) << s - - + + - - + + @@ -112518,12 +112518,13 @@ std::cout << tmpl.render({"what", "World"}) << s - - + + + - - + + @@ -112621,13 +112622,13 @@ std::cout << tmpl.render({"what", "World"}) << s - - - - + + + + - - + + @@ -112645,16 +112646,18 @@ std::cout << tmpl.render({"what", "World"}) << s - - - - + + + + + - - + + - - + + + @@ -112731,8 +112734,8 @@ std::cout << tmpl.render({"what", "World"}) << s - - + + @@ -112854,10 +112857,10 @@ std::cout << tmpl.render({"what", "World"}) << s - - - - + + + + @@ -112908,8 +112911,8 @@ std::cout << tmpl.render({"what", "World"}) << s - - + + @@ -112925,18 +112928,18 @@ std::cout << tmpl.render({"what", "World"}) << s - - + + - - + + - - + + @@ -112954,8 +112957,8 @@ std::cout << tmpl.render({"what", "World"}) << s - - + + @@ -112966,18 +112969,18 @@ std::cout << tmpl.render({"what", "World"}) << s - - + + - + - + @@ -113042,12 +113045,12 @@ std::cout << tmpl.render({"what", "World"}) << s - - + + - + @@ -113383,32 +113386,39 @@ std::cout << tmpl.render({"what", "World"}) << s - - - + + + + + + - + - + - + - - + + + + + - - - - + + + + + @@ -113428,27 +113438,27 @@ std::cout << tmpl.render({"what", "World"}) << s - - - + + + - - - - + + + + - - + + - - + + @@ -113461,6 +113471,10 @@ std::cout << tmpl.render({"what", "World"}) << s + + + + @@ -113513,6 +113527,7 @@ std::cout << tmpl.render({"what", "World"}) << s +