data::share::StringTemplate. Format string template using ValueProvider.

This commit is contained in:
lganzzzo 2020-07-06 02:39:20 +03:00
parent 9003a680c0
commit a6aaa1eb48
4 changed files with 219 additions and 48 deletions

View File

@ -28,6 +28,38 @@
namespace oatpp { namespace data { namespace share {
StringTemplate::VectorValueProvider::VectorValueProvider(const std::vector<oatpp::String> *params)
: m_params(params)
{}
oatpp::String StringTemplate::VectorValueProvider::getValue(const Variable& variable, v_uint32 index) {
(void) variable;
return m_params->at(index);
}
StringTemplate::MapValueProvider::MapValueProvider(const std::unordered_map<oatpp::String, oatpp::String> *params)
: m_params(params)
{}
oatpp::String StringTemplate::MapValueProvider::getValue(const Variable& variable, v_uint32 index) {
(void) index;
auto it = m_params->find(variable.name);
if(it != m_params->end()) {
return it->second;
}
return nullptr;
}
StringTemplate::SingleValueProvider::SingleValueProvider(const oatpp::String& value)
: m_value(value)
{}
oatpp::String StringTemplate::SingleValueProvider::getValue(const Variable& variable, v_uint32 index) {
(void) variable;
(void) index;
return m_value;
}
StringTemplate::StringTemplate(const oatpp::String& text, std::vector<Variable>&& variables)
: m_text(text)
, m_variables(variables)
@ -50,23 +82,24 @@ StringTemplate::StringTemplate(const oatpp::String& text, std::vector<Variable>&
}
}
void StringTemplate::format(stream::ConsistentOutputStream* stream, const std::vector<oatpp::String>& params) const {
if(params.size() != m_variables.size()) {
throw std::runtime_error("[oatpp::data::share::StringTemplate::format()]: Error. Wrong number of arguments.");
}
void StringTemplate::format(stream::ConsistentOutputStream* stream, ValueProvider* valueProvider) const {
v_buff_size prevPos = 0;
for(v_int32 i = 0; i < m_variables.size(); i++) {
for(v_uint32 i = 0; i < m_variables.size(); i++) {
const auto& var = m_variables[i];
const auto& param = params[i];
const auto& value = valueProvider->getValue(var, i);
if(!value) {
throw std::runtime_error("[oatpp::data::share::StringTemplate::format()]: "
"Error. No value provided for the parameter name=" + var.name->std_str());
}
if(prevPos < var.posStart) {
stream->writeSimple(m_text->getData() + prevPos, var.posStart - prevPos);
}
stream->writeSimple(param->getData(), param->getSize());
stream->writeSimple(value->getData(), value->getSize());
prevPos = var.posEnd + 1;
@ -78,33 +111,19 @@ void StringTemplate::format(stream::ConsistentOutputStream* stream, const std::v
}
void StringTemplate::format(stream::ConsistentOutputStream* stream, const std::vector<oatpp::String>& params) const {
VectorValueProvider vp(&params);
format(stream, &vp);
}
void StringTemplate::format(stream::ConsistentOutputStream* stream, const std::unordered_map<oatpp::String, oatpp::String>& params) const {
MapValueProvider vp(&params);
format(stream, &vp);
}
v_buff_size prevPos = 0;
for(v_int32 i = 0; i < m_variables.size(); i++) {
const auto& var = m_variables[i];
auto paramIt = params.find(var.name);
if(paramIt == params.end()) {
throw std::runtime_error("[oatpp::data::share::StringTemplate::format()]: Error. Parameter not found. Name=" + var.name->std_str());
}
const auto& param = paramIt->second;
if(prevPos < var.posStart) {
stream->writeSimple(m_text->getData() + prevPos, var.posStart - prevPos);
}
stream->writeSimple(param->getData(), param->getSize());
prevPos = var.posEnd + 1;
}
if(prevPos < m_text->getSize()) {
stream->writeSimple(m_text->getData() + prevPos, m_text->getSize() - prevPos);
}
void StringTemplate::format(stream::ConsistentOutputStream* stream, const oatpp::String& singleValue) const {
SingleValueProvider vp(singleValue);
format(stream, &vp);
}
oatpp::String StringTemplate::format(const std::vector<oatpp::String>& params) const {
@ -119,4 +138,14 @@ oatpp::String StringTemplate::format(const std::unordered_map<oatpp::String, oat
return stream.toString();
}
oatpp::String StringTemplate::format(const oatpp::String& singleValue) const {
stream::BufferOutputStream stream;
format(&stream, singleValue);
return stream.toString();
}
const std::vector<StringTemplate::Variable>& StringTemplate::getTemplateVariables() const {
return m_variables;
}
}}}

View File

@ -33,13 +33,90 @@
namespace oatpp { namespace data { namespace share {
/**
* String template.
*/
class StringTemplate {
public:
/**
* Template variable.
*/
struct Variable {
/**
* Position of the first char in the original template string.
*/
v_buff_size posStart;
/**
* Position of the last char in the original template string.
*/
v_buff_size posEnd;
/**
* Name of the template variable.
*/
oatpp::String name;
/**
* Some auxiliary data.
*/
std::shared_ptr<void> extra;
};
public:
/**
* Abstract template value provider.
*/
class ValueProvider {
public:
/**
* Default virtual destructor.
*/
virtual ~ValueProvider() = default;
/**
* Get value for variable.
* @param variable - &l:StringTemplate::Variable;.
* @param index - index of the variable in the template.
* @return - value for the given variable.
*/
virtual oatpp::String getValue(const Variable& variable, v_uint32 index) = 0;
};
/**
* Provider of template variable-values based on the std::vector.
*/
class VectorValueProvider : public ValueProvider {
private:
const std::vector<oatpp::String>* m_params;
public:
VectorValueProvider(const std::vector<oatpp::String>* params);
oatpp::String getValue(const Variable& variable, v_uint32 index) override;
};
/**
* Provider of template variable-values based on the std::unordered_map.
*/
class MapValueProvider : public ValueProvider {
private:
const std::unordered_map<oatpp::String, oatpp::String>* m_params;
public:
MapValueProvider(const std::unordered_map<oatpp::String, oatpp::String>* params);
oatpp::String getValue(const Variable& variable, v_uint32 index) override;
};
/**
* Provider of template variable-values which returns the same value for all variables.
*/
class SingleValueProvider : public ValueProvider {
private:
oatpp::String m_value;
public:
SingleValueProvider(const oatpp::String& value);
oatpp::String getValue(const Variable& variable, v_uint32 index) override;
};
private:
@ -47,14 +124,68 @@ private:
std::vector<Variable> m_variables;
public:
/**
* Constructor.
* @param text - original template text.
* @param variables - template variables.
*/
StringTemplate(const oatpp::String& text, std::vector<Variable>&& variables);
/**
* Format template.
* @param stream - stream to write result to.
* @param valueProvider - &l:StringTemplate::ValueProvider;.
*/
void format(stream::ConsistentOutputStream* stream, ValueProvider* valueProvider) const;
/**
* Format template using &l:StringTemplate::VectorValueProvider;.
* @param stream - stream to write result to.
* @param params - `std::vector<oatpp::String>`.
*/
void format(stream::ConsistentOutputStream* stream, const std::vector<oatpp::String>& params) const;
/**
* Format template using &l:StringTemplate::MapValueProvider;.
* @param stream - stream to write result to.
* @param params - `std::unordered_map<oatpp::String, oatpp::String>`.
*/
void format(stream::ConsistentOutputStream* stream, const std::unordered_map<oatpp::String, oatpp::String>& params) const;
/**
* Format template using &l:StringTemplate::SingleValueProvider;.
* @param stream - stream to write result to.
* @param singleValue - value.
*/
void format(stream::ConsistentOutputStream* stream, const oatpp::String& singleValue) const;
/**
* Format template using &l:StringTemplate::VectorValueProvider;.
* @param params - `std::vector<oatpp::String>`.
* @return - resultant string.
*/
oatpp::String format(const std::vector<oatpp::String>& params) const;
/**
* Format template using &l:StringTemplate::MapValueProvider;.
* @param params - `std::unordered_map<oatpp::String, oatpp::String>`.
* @return - resultant string.
*/
oatpp::String format(const std::unordered_map<oatpp::String, oatpp::String>& params) const;
/**
* Format template using &l:StringTemplate::SingleValueProvider;.
* @param singleValue - value.
* @return - resultant string.
*/
oatpp::String format(const oatpp::String& singleValue) const;
/**
* Get all template variables.
* @return - `std::vector` of &l:StringTemplate::Variable;.
*/
const std::vector<Variable>& getTemplateVariables() const;
};
}}}

View File

@ -35,7 +35,7 @@
namespace oatpp { namespace db {
class Client {
private:
protected:
std::shared_ptr<Executor> m_executor;
public:
@ -50,17 +50,6 @@ public:
// "DELETE FROM user WHERE userId=:userId",
// PARAM(String, userId))
oatpp::data::share::StringTemplate Z_QUERY_TEMPLATE_getUserById =
m_executor->parseQueryTemplate("SELECT * FROM user WHERE userId=:userId");
oatpp::db::QueryResult getUserById(const oatpp::String& userId) {
std::unordered_map<oatpp::String, oatpp::Any> __params;
__params["userId"] = userId;
return m_executor->execute(Z_QUERY_TEMPLATE_getUserById, __params);
}
};
}}

View File

@ -35,7 +35,7 @@ void StringTemplateTest::onRun() {
{
OATPP_LOGI(TAG, "Case1 ...");
StringTemplate t("{} World!", {{0, 1, "p1"}});
auto result = t.format({"Hello"});
auto result = t.format({oatpp::String("Hello")});
OATPP_ASSERT(result == "Hello World!");
OATPP_LOGI(TAG, "OK");
}
@ -51,7 +51,7 @@ void StringTemplateTest::onRun() {
{
OATPP_LOGI(TAG, "Case3 ...");
StringTemplate t("Hello {}", {{6, 7, "p1"}});
auto result = t.format({"World!"});
auto result = t.format({oatpp::String("World!")});
OATPP_ASSERT(result == "Hello World!");
OATPP_LOGI(TAG, "OK");
}
@ -67,7 +67,7 @@ void StringTemplateTest::onRun() {
{
OATPP_LOGI(TAG, "Case5 ...");
StringTemplate t("Hello {} World!", {{6, 7, "p1"}});
auto result = t.format({"My"});
auto result = t.format({oatpp::String("My")});
OATPP_ASSERT(result == "Hello My World!");
OATPP_LOGI(TAG, "OK");
}
@ -96,6 +96,28 @@ void StringTemplateTest::onRun() {
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Case9 ...");
StringTemplate t("? ? ?", {{0, 0, "p1"}, {2, 2, "p2"}, {4, 4, "p3"}});
auto result = t.format("A");
OATPP_ASSERT(result == "A A A");
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Case10 ...");
StringTemplate t("? ? ?",
{
{0, 0, "p1", std::make_shared<oatpp::base::Countable>()},
{2, 2, "p2", std::make_shared<oatpp::base::Countable>()},
{4, 4, "p3", std::make_shared<oatpp::base::Countable>()}
}
);
auto result = t.format("(A)");
OATPP_ASSERT(result == "(A) (A) (A)");
OATPP_LOGI(TAG, "OK");
}
}
}}}}}