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:
parent
830ab42c49
commit
4958a83ddb
1 changed files with 85 additions and 2 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue