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 <boost/variant/apply_visitor.hpp>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <functional>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace duck { namespace sl {
|
namespace duck { namespace sl {
|
||||||
#if defined(APPLY_VERBOSE)
|
#if defined(APPLY_VERBOSE)
|
||||||
|
@ -48,6 +50,7 @@ namespace duck { namespace sl {
|
||||||
EntryNode
|
EntryNode
|
||||||
>>;
|
>>;
|
||||||
using MustacheEntryMap = std::map<std::string, MustacheEntry>;
|
using MustacheEntryMap = std::map<std::string, MustacheEntry>;
|
||||||
|
typedef std::function<void(std::size_t)> FixLengthCommand;
|
||||||
|
|
||||||
struct EntryNode {
|
struct EntryNode {
|
||||||
explicit EntryNode (const std::string_view& parName) :
|
explicit EntryNode (const std::string_view& parName) :
|
||||||
|
@ -106,6 +109,72 @@ namespace duck { namespace sl {
|
||||||
EntryNode& m_root;
|
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 (
|
mstch::map to_mustache_dict_recursive (
|
||||||
const EntryNode& parNode,
|
const EntryNode& parNode,
|
||||||
std::string_view parSrc,
|
std::string_view parSrc,
|
||||||
|
@ -266,7 +335,7 @@ namespace duck { namespace sl {
|
||||||
return empty_retval;
|
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;
|
typedef ItemCountingVisitor ITC;
|
||||||
using boost::apply_visitor;
|
using boost::apply_visitor;
|
||||||
|
|
||||||
|
@ -283,10 +352,13 @@ namespace duck { namespace sl {
|
||||||
|
|
||||||
void fill_with_xpaths (
|
void fill_with_xpaths (
|
||||||
mstch::map& parOut,
|
mstch::map& parOut,
|
||||||
|
std::vector<FixLengthCommand>& parFixCommands,
|
||||||
const EntryNode& parNode,
|
const EntryNode& parNode,
|
||||||
std::string_view parSrc,
|
std::string_view parSrc,
|
||||||
XPathRunner& parRunner
|
XPathRunner& parRunner
|
||||||
) {
|
) {
|
||||||
|
using std::placeholders::_1;
|
||||||
|
|
||||||
for (const XPathElement* xpath : parNode.xpaths) {
|
for (const XPathElement* xpath : parNode.xpaths) {
|
||||||
assert(xpath);
|
assert(xpath);
|
||||||
std::cout << "Running query for \"" << xpath->name << "\"\n";
|
std::cout << "Running query for \"" << xpath->name << "\"\n";
|
||||||
|
@ -306,6 +378,11 @@ namespace duck { namespace sl {
|
||||||
else {
|
else {
|
||||||
parOut[xpath->name] = std::string();
|
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
|
XPathRunner& parRunner
|
||||||
) {
|
) {
|
||||||
mstch::map retval;
|
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);
|
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;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue