String replacements

parent e6cea54b
Subproject commit 764a858a5ec1e27c2d6ea527a563bb2eb2e52e5d
Subproject commit ae800437306413e900d5ca018eaff438e0d6c971
......@@ -46,6 +46,11 @@ public:
replacement = std::move(*rep);
}
void expand(FormattedString& output) const
{
output.append(replacement);
}
private:
std::string identifier;
FormattedString replacement;
......@@ -112,6 +117,11 @@ public:
return filtered().encode(formatter, context);
}
void expand(FormattedString& output) const
{
output.append_packed(filtered());
}
private:
std::string filter;
std::vector<FormattedString> arguments;
......@@ -212,7 +222,7 @@ public:
std::string to_string(const Formatter& formatter, Formatter::Context* context) const
{
std::string output;
for ( const auto& item : source )
for ( const auto& item : source.expanded() )
{
FormattedString replace;
replace.push_back(item);
......
......@@ -148,6 +148,26 @@ namespace detail {
return element::to_string(formatter, t, context);
}
/**
* \brief Calls a member expand
*/
template<class T>
auto expand_dispatch(T&& t, FormattedString& output, OveloadTag)
-> melanolib::DummyType<bool, decltype(t.expand(std::declval<FormattedString&>()))>
{
t.expand(output);
return true;
}
/**
* \brief Dummy fallback
*/
template<class T>
bool expand_dispatch(T&& t, FormattedString& output, ...)
{
return false;
}
} // namespace detail
/**
......@@ -163,6 +183,7 @@ private:
virtual std::unique_ptr<HolderBase> clone() const = 0;
virtual const std::type_info& type() const noexcept = 0;
virtual void replace(const ReplacementFunctor& repl) = 0;
virtual bool expand(FormattedString& out) const = 0;
};
template<class T>
......@@ -180,6 +201,11 @@ private:
detail::replace_dispatch(object, repl, detail::OveloadTag{});
}
bool expand(FormattedString& repl) const override
{
return detail::expand_dispatch(object, repl, detail::OveloadTag{});
}
std::unique_ptr<HolderBase> clone() const override
{
return melanolib::New<Holder<T>>(object);
......@@ -267,6 +293,8 @@ public:
return holder->type() == typeid(HeldType<T>);
}
void expand(FormattedString& output) const;
private:
explicit Element(std::unique_ptr<HolderBase>&& holder)
: holder(std::move(holder))
......@@ -552,6 +580,14 @@ public:
return str;
}
FormattedString expanded() const
{
FormattedString output;
for ( const Element& element : elements )
element.expand(output);
return output;
}
// Stream-like operations
template <class T>
FormattedString& operator<<(T&& obj) &
......@@ -602,6 +638,13 @@ FormattedString implode (const FormattedString& separator, const Container& elem
}
inline void Element::expand(FormattedString& output) const
{
if ( !holder->expand(output) )
output.append(clone());
}
using FormattedProperties = std::unordered_map<std::string, FormattedString>;
} // namespace string
......
......@@ -854,4 +854,12 @@ BOOST_AUTO_TEST_CASE( test_Config_for )
BOOST_CHECK_EQUAL( decoded.size(), 1 );
BOOST_CHECK( cast<string::ForStatement>(decoded[0]) );
BOOST_CHECK_EQUAL( decoded.encode(fmt), "$(1)$(2)$(3)foo" );
decoded = fmt.decode("$(for color $colors)${color}foo$(endfor)");
BOOST_CHECK_EQUAL( decoded.size(), 1 );
FormattedString colors;
colors << color::red << color::green << color::yellow;
decoded.replace("colors", colors);
BOOST_CHECK( cast<string::ForStatement>(decoded[0]) );
BOOST_CHECK_EQUAL( decoded.encode(fmt), "$(1)foo$(2)foo$(3)foo" );
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment