Trying to get default value filling fixed.

I'm not sure it always works, but the idea is that this should
find the maximum size of all arrays resulting from a scraplang
struct query and make all entries the same length filling them
with:
1) the default value if one was given in scraplang
2) the value of the last entry in the array being filled
3) just empty values

It seems to work but I can't say I ran very extensive tests.
I'll test more in the future and fix as needed.
This commit is contained in:
King_DuckZ 2020-04-02 02:26:44 +02:00
parent 830ab42c49
commit 4958a83ddb

View file

@ -30,6 +30,8 @@
#include <boost/variant/apply_visitor.hpp>
#include <string_view>
#include <list>
#include <functional>
#include <algorithm>
namespace duck { namespace sl {
#if defined(APPLY_VERBOSE)
@ -48,6 +50,7 @@ namespace duck { namespace sl {
EntryNode
>>;
using MustacheEntryMap = std::map<std::string, MustacheEntry>;
typedef std::function<void(std::size_t)> FixLengthCommand;
struct EntryNode {
explicit EntryNode (const std::string_view& parName) :
@ -106,6 +109,72 @@ namespace duck { namespace sl {
EntryNode& m_root;
};
class FillWithClonesVisitor : public boost::static_visitor<mstch::node&&> {
public:
explicit FillWithClonesVisitor (std::size_t exp_size) :
m_expected_size(exp_size)
{ }
virtual mstch::node&& operator()(mstch::array&& parOut) {
if (parOut.empty()) {
parOut.resize(m_expected_size);
}
else {
std::fill_n(
std::back_inserter(parOut),
std::max(m_expected_size, parOut.size()) - parOut.size(),
parOut.front()
);
}
m_retval = std::move(parOut);
return std::move(m_retval);
}
template <typename T>
mstch::node&& operator()(T&& parOut) {
mstch::array retval;
retval.reserve(m_expected_size);
retval.push_back(std::move(parOut));
return (*this)(std::move(retval));
}
protected:
mstch::node m_retval;
std::size_t m_expected_size;
};
class FillWithStringsVisitor : public FillWithClonesVisitor {
public:
FillWithStringsVisitor (const std::string& parVal, std::size_t exp_size) :
FillWithClonesVisitor(exp_size),
m_value(parVal)
{ }
mstch::node&& operator()(mstch::array&& parOut) override {
std::fill_n(
std::back_inserter(parOut),
std::max(m_expected_size, parOut.size()) - parOut.size(),
m_value.get()
);
m_retval = std::move(parOut);
return std::move(m_retval);
}
using FillWithClonesVisitor::operator();
private:
std::reference_wrapper<const std::string> m_value;
};
void fill_with_defaults (mstch::map& parMap, std::size_t parTotal, const std::string& parKey, const std::string& parDefault) {
FillWithStringsVisitor visitor(parDefault, parTotal);
parMap[parKey] = boost::apply_visitor(visitor, std::move(parMap[parKey]));
}
void fill_with_last_item_clones (mstch::map& parMap, std::size_t parTotal, const std::string& parKey) {
FillWithClonesVisitor visitor(parTotal);
parMap[parKey] = boost::apply_visitor(visitor, std::move(parMap[parKey]));
}
mstch::map to_mustache_dict_recursive (
const EntryNode& parNode,
std::string_view parSrc,
@ -266,7 +335,7 @@ namespace duck { namespace sl {
return empty_retval;
}
std::size_t largest_array_size_in (mstch::map& parMap) {
std::size_t largest_array_size_in (const mstch::map& parMap) {
typedef ItemCountingVisitor ITC;
using boost::apply_visitor;
@ -283,10 +352,13 @@ namespace duck { namespace sl {
void fill_with_xpaths (
mstch::map& parOut,
std::vector<FixLengthCommand>& parFixCommands,
const EntryNode& parNode,
std::string_view parSrc,
XPathRunner& parRunner
) {
using std::placeholders::_1;
for (const XPathElement* xpath : parNode.xpaths) {
assert(xpath);
std::cout << "Running query for \"" << xpath->name << "\"\n";
@ -306,6 +378,11 @@ namespace duck { namespace sl {
else {
parOut[xpath->name] = std::string();
}
if (xpath->def_val)
parFixCommands.push_back(std::bind(&fill_with_defaults, std::ref(parOut), _1, std::cref(xpath->name), std::cref(*xpath->def_val)));
else
parFixCommands.push_back(std::bind(&fill_with_last_item_clones, std::ref(parOut), _1, std::cref(xpath->name)));
}
}
@ -337,10 +414,16 @@ namespace duck { namespace sl {
XPathRunner& parRunner
) {
mstch::map retval;
std::vector<FixLengthCommand> fix_commands;
fill_with_xpaths(retval, parNode, parSrc, parRunner);
fill_with_xpaths(retval, fix_commands, parNode, parSrc, parRunner);
fill_with_structs(retval, parNode, parSrc, parRunner);
const std::size_t largest = largest_array_size_in(retval);
for (const auto& command : fix_commands) {
command(largest);
}
return retval;
}