instead of morm::Wrapper let the Var<> has a child's map

This commit is contained in:
Tomasz Sowa 2021-10-27 14:23:48 +02:00
parent a61fd2dcd0
commit 6d79cdb2fc
2 changed files with 325 additions and 82 deletions

View File

@ -147,7 +147,7 @@ private:
Var<StreamType> * variable;
#ifdef EZC_HAS_MORM_LIBRARY
morm::Wrapper * wrapper;
Var<StreamType> * wrapper;
size_t field_index;
#endif
@ -302,10 +302,10 @@ private:
Var<StreamType> & result,
std::vector<Var<StreamType>> & parameters);
void PrintDate(pt::Date * date, Var<StreamType> & result, std::vector<Var<StreamType>> & parameters);
bool PrintDatePart(pt::Date * date, const std::wstring & field, Var<StreamType> & result, std::vector<Var<StreamType>> & parameters);
void PrintDate(pt::Date & date, std::vector<Var<StreamType>> & parameters, Var<StreamType> & result);
//bool PrintDatePart(pt::Date & date, const std::wstring & field, std::vector<Var<StreamType>> & parameters, Var<StreamType> & result);
bool CallDate(FindHelper & find_helper, std::vector<std::wstring> & fields, Var<StreamType> & result, std::vector<Var<StreamType>> & parameters);
//bool CallDate(pt::Date & date, const std::wstring & name, std::vector<std::wstring> & fields, size_t & field_index, std::vector<Var<StreamType>> & parameters, Var<StreamType> & result);
void PrintLastSpaceField(pt::Space * space, Var<StreamType> & result, std::vector<Var<StreamType>> & parameters);
void CallSpaceObjectForLastField(Var<StreamType> & result, std::vector<Var<StreamType>> & parameters, pt::Space * space);
@ -320,10 +320,11 @@ private:
bool CallSpace(morm::SpaceWrapper * space_wrapper, const std::wstring & name, size_t & field_index, std::vector<std::wstring> & fields, Var<StreamType> & result, std::vector<Var<StreamType>> & parameters);
#ifdef EZC_HAS_MORM_LIBRARY
bool CallModelField(morm::Model & model, const std::wstring & field, Var<StreamType> & result, std::vector<Var<StreamType>> & parameters, const StreamType & in_stream);
bool CallModel(morm::Model & model, FindHelper & find_helper, std::vector<std::wstring> & fields, Var<StreamType> & result, std::vector<Var<StreamType>> & parameters, const StreamType & in_stream);
void FindLastModelWrapper(FindHelper & find_helper, std::vector<std::wstring> & fields);
bool CallWrapper(FindHelper & find_helper, std::vector<std::wstring> & fields, Var<StreamType> & result, std::vector<Var<StreamType>> & parameters, const StreamType & in_stream);
bool CallModelField(morm::Model & model, const std::wstring & field, Var<StreamType> & result, std::vector<Var<StreamType>> & parameters);
// bool CallModel(morm::Model & model, const std::wstring & name, std::vector<std::wstring> & fields, size_t field_index,
// std::vector<Var<StreamType>> & parameters, Var<StreamType> & result);
// void FindLastModelWrapper(FindHelper & find_helper, std::vector<std::wstring> & fields);
// bool CallWrapper(FindHelper & find_helper, std::vector<std::wstring> & fields, Var<StreamType> & result, std::vector<Var<StreamType>> & parameters, const StreamType & in_stream);
bool XXXRenameMe(Var<StreamType> & variable, std::vector<std::wstring> & fields, size_t & field_index, Var<StreamType> & result, std::vector<Var<StreamType>> & parameters, const StreamType & in_stream);
@ -1120,7 +1121,7 @@ void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::DumpModel
template<class StreamType, bool is_pikotools_stream, bool is_autoescape_stream>
void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::PrintDate(
pt::Date * date, Var<StreamType> & result, std::vector<Var<StreamType>> & parameters)
pt::Date & date, std::vector<Var<StreamType>> & parameters, Var<StreamType> & result)
{
bool is_roman = HasParam(parameters, L"roman");
bool is_no_sec = HasParam(parameters, L"no_sec");
@ -1130,7 +1131,7 @@ void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::PrintDate
if( only_date )
{
result.type = Var<StreamType>::TYPE_STREAM;
date->SerializeYearMonthDay(result.stream, is_roman);
date.SerializeYearMonthDay(result.stream, is_roman);
}
else
if( only_time )
@ -1138,21 +1139,26 @@ void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::PrintDate
result.type = Var<StreamType>::TYPE_STREAM;
if( is_no_sec )
date->SerializeHourMin(result.stream);
date.SerializeHourMin(result.stream);
else
date->SerializeHourMinSec(result.stream);
date.SerializeHourMinSec(result.stream);
}
else
{
result.type = Var<StreamType>::TYPE_STREAM;
date->Serialize(result.stream, is_roman, !is_no_sec);
date.Serialize(result.stream, is_roman, !is_no_sec);
}
}
/*
* these can be made as a simple function (e.g. from winix)
* as a first argument let they take pt::Date
*/
/*
template<class StreamType, bool is_pikotools_stream, bool is_autoescape_stream>
bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::PrintDatePart(
pt::Date * date, const std::wstring & field, Var<StreamType> & result, std::vector<Var<StreamType>> & parameters)
pt::Date & date, const std::wstring & field, std::vector<Var<StreamType>> & parameters, Var<StreamType> & result)
{
bool is_test = IsTestingFunctionExistence();
@ -1161,7 +1167,7 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::PrintDate
if( !is_test )
{
result.type = Var<StreamType>::TYPE_STREAM;
result.stream << date->year;
result.stream << date.year;
}
}
else
@ -1173,9 +1179,9 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::PrintDate
result.type = Var<StreamType>::TYPE_STREAM;
if( is_roman )
pt::Date::SerializeMonthAsRoman(result.stream, date->month);
pt::Date::SerializeMonthAsRoman(result.stream, date.month);
else
result.stream << date->month;
result.stream << date.month;
}
}
else
@ -1184,7 +1190,7 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::PrintDate
if( !is_test )
{
result.type = Var<StreamType>::TYPE_STREAM;
result.stream << date->day;
result.stream << date.day;
}
}
else
@ -1193,7 +1199,7 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::PrintDate
if( !is_test )
{
result.type = Var<StreamType>::TYPE_STREAM;
result.stream << date->hour;
result.stream << date.hour;
}
}
else
@ -1202,7 +1208,7 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::PrintDate
if( !is_test )
{
result.type = Var<StreamType>::TYPE_STREAM;
result.stream << date->min;
result.stream << date.min;
}
}
else
@ -1211,7 +1217,7 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::PrintDate
if( !is_test )
{
result.type = Var<StreamType>::TYPE_STREAM;
result.stream << date->sec;
result.stream << date.sec;
}
}
else
@ -1221,45 +1227,41 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::PrintDate
return true;
}
*/
/*
template<class StreamType, bool is_pikotools_stream, bool is_autoescape_stream>
bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::CallDate(
FindHelper & find_helper, std::vector<std::wstring> & fields, Var<StreamType> & result, std::vector<Var<StreamType>> & parameters)
pt::Date & date, const std::wstring & name, std::vector<std::wstring> & fields, size_t field_index, std::vector<Var<StreamType>> & parameters, Var<StreamType> & result)
{
bool found = true;
bool all_fields_known = (find_helper.field_index == fields.size());
bool last_field_not_known = (find_helper.field_index + 1 == fields.size());
bool all_fields_known = (field_index == fields.size());
if( all_fields_known )
{
PrintDate(find_helper.wrapper->date, result, parameters);
}
else
if( last_field_not_known )
{
if( !PrintDatePart(find_helper.wrapper->date, fields[find_helper.field_index], result, parameters) )
{
if( !IsTestingFunctionExistence() )
{
CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", unknown property ", fields[find_helper.field_index].c_str(), L" of date object");
}
found = false;
}
PrintDate(date, parameters, result);
}
else
{
if( !IsTestingFunctionExistence() )
{
CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", ", fields[find_helper.field_index].c_str(), L" is not a model nor a model container nor a space");
}
found = PrintDatePart(date, fields[field_index], result, parameters);
found = false;
// if( found )
// field_index += 1;
// {
// if( !IsTestingFunctionExistence() )
// {
// CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", unknown property ", fields[find_helper.field_index].c_str(), L" of date object");
// }
//
// found = false;
// }
}
return found;
}
*/
@ -1488,7 +1490,7 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::CallSpace
template<class StreamType, bool is_pikotools_stream, bool is_autoescape_stream>
bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::CallModelField(
morm::Model & model, const std::wstring & field, Var<StreamType> & result, std::vector<Var<StreamType>> & parameters, const StreamType & in_stream)
morm::Model & model, const std::wstring & field, Var<StreamType> & result, std::vector<Var<StreamType>> & parameters)
{
/*
* if 'field' is a POD type then 'str' will be used in get_raw_value()
@ -1496,27 +1498,28 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::CallModel
* if 'field' is a getter method which takes Env<> then out_stream will be used and 'str' will be empty
*
*/
pt::WTextStream str;
//pt::WTextStream str;
bool found = false;
StreamType fake_stream;
Env<StreamType> info(result, parameters, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item);
found = model.get_raw_value(nullptr, field.c_str(), nullptr, info, str, false);
Env<StreamType> info(result, parameters, fake_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item);
found = model.get_raw_value(nullptr, field.c_str(), nullptr, info);
if( found && !str.empty())
{
bool no_escape = HasParam(parameters, L"raw", L"noescape");
CopyStream(str, result.stream, !no_escape);
result.type = Var<StreamType>::TYPE_STREAM;
}
// if( found && !str.empty())
// {
// bool no_escape = HasParam(parameters, L"raw", L"noescape");
// CopyStream(str, result.stream, !no_escape);
// result.type = Var<StreamType>::TYPE_STREAM;
// }
return found;
}
/*
template<class StreamType, bool is_pikotools_stream, bool is_autoescape_stream>
bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::CallModel(
morm::Model & model, FindHelper & find_helper, std::vector<std::wstring> & fields,
Var<StreamType> & result, std::vector<Var<StreamType>> & parameters, const StreamType & in_stream)
morm::Model & model, const std::wstring & name, std::vector<std::wstring> & fields, size_t field_index,
std::vector<Var<StreamType>> & parameters, Var<StreamType> & result)
{
bool found = true;
@ -1554,53 +1557,71 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::CallModel
return found;
}
*/
/*
template<class StreamType, bool is_pikotools_stream, bool is_autoescape_stream>
void Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::FindLastModelWrapper(
FindHelper & find_helper, std::vector<std::wstring> & fields)
Var<StreamType> & var_parent, std::vector<std::wstring> & fields, size_t & field_index)
{
for(find_helper.field_index = 0 ; find_helper.field_index < fields.size() && find_helper.wrapper->has_model_object() ; ++find_helper.field_index)
{
std::wstring & field = fields[find_helper.field_index];
morm::Wrapper * child_wrapper = find_helper.wrapper->find_child(field);
Var<StreamType> * var = &var_parent;
if( !child_wrapper )
for( ; field_index < fields.size() && var->has_model_object() ; ++field_index)
{
std::wstring & field = fields[field_index];
Var<StreamType> * child_var = var->find_child(field);
if( !child_var )
{
morm::Model * model = nullptr;
if( find_helper.wrapper->model )
if( var->model )
{
model = find_helper.wrapper->model;
model = var->model;
}
else
if( find_helper.wrapper->model_container_wrapper )
if( var->model_container_wrapper )
{
model = find_helper.wrapper->model_container_wrapper->get_model();
model = var->model_container_wrapper->get_model();
// this can return null for lists/vectors in a case when the iterator is not pointing to a valid item
}
if( model )
{
// IMPROVE ME there'll be only one method to call a model
morm::Wrapper new_wrapper = model->get_wrapper(nullptr, field.c_str());
if( new_wrapper.has_object() )
{
child_wrapper = find_helper.wrapper->add_child(field, new_wrapper);
Var<StreamType> child;
if( new_wrapper.model )
child.set(*new_wrapper.model);
if( new_wrapper.model_container_wrapper )
child.set(*new_wrapper.model_container_wrapper);
if( new_wrapper.date )
child.set(*new_wrapper.date);
if( new_wrapper.space_wrapper )
child.set(*new_wrapper.space_wrapper);
child_var = var->add_child(field, new_wrapper);
}
//////////////////////////////////////////////////////////////////////
}
}
if( !child_wrapper )
if( !child_var )
break;
find_helper.wrapper = child_wrapper;
var = child_var;
}
}
*/
/*
template<class StreamType, bool is_pikotools_stream, bool is_autoescape_stream>
bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::CallWrapper(
FindHelper & find_helper, std::vector<std::wstring> & fields,
@ -1669,6 +1690,7 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::CallWrapp
return found;
}
*/
#endif
@ -1867,22 +1889,43 @@ Var<StreamType> * Generator<StreamType, is_pikotools_stream, is_autoescape_strea
do
{
const std::wstring * pname = (field_index == 0)? &name : &fields[field_index - 1];
Var<StreamType> * var = FindInScope(*pname);
Var<StreamType> * old_var = var;
var = nullptr;
if( field_index > 1 && old_var )
{
var = old_var->find_child(*pname);
}
if( !var )
{
var = FindInScope(*pname);
}
if( var )
{
/*
* fix me
* this is incorrect, as the parameters would be passed to the first function
* if the first function is a model we do not pass parameters to it, but to a field of the model (our next field)
*
*/
if( was_evaluated )
{
Var<StreamType> improve_me;
EvaluateVariable(*var, res, improve_me);
EvaluateVariable(name, *var, fields, field_index, res, improve_me);
res[0] = improve_me;
}
else
{
if( EvaluateVariable(*var, parameters, res[0]) )
if( EvaluateVariable(name, *var, fields, field_index, parameters, res[0]) )
was_evaluated = true;
}
}
else
{
// log something
}
field_index += 1;
}
@ -1898,6 +1941,7 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::EvaluateV
{
StreamType fake_stream;
bool status = false;
bool all_fields_known = (field_index == fields.size());
if( var.type == Var<StreamType>::TYPE_FUNCTION )
{
@ -1916,7 +1960,7 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::EvaluateV
{
if( var.model )
{
//status = CallModel(*var.model, name, fields, field_index, parameters, result);
status = CallModelField(*var.model, name, result, parameters);
}
else
{
@ -1924,6 +1968,31 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::EvaluateV
}
}
if( var.type == Var<StreamType>::TYPE_MODEL_CONTAINER_WRAPPER && var->model_container_wrapper )
{
morm::Model * model = var.model_container_wrapper->get_model();
if( model )
{
status = CallModelField(*model, name, result, parameters);
}
else
{
// can be printed even for [if-def...]
CreateMsg(L"model ", name, fields, L" is not initialized, have you forgotten to use [for ...] statement?");
status = false;
}
if( all_fields_known )
{
if( is_generating_for )
{
var.model_container_wrapper->increment_iterator();
var.clear_childs();
}
}
}
if( var.type == Var<StreamType>::TYPE_SPACE_WRAPPER )
{
if( var.space_wrapper )
@ -1936,6 +2005,12 @@ bool Generator<StreamType, is_pikotools_stream, is_autoescape_stream>::EvaluateV
}
}
if( var.type == Var<StreamType>::TYPE_DATE && var.date )
{
if( all_fields_known )
PrintDate(*var.date, parameters, result);
}
return status;
}

178
src/var.h
View File

@ -42,6 +42,7 @@
#include "date/date.h"
#include "modelcontainerwrapper.h"
#include "textstream/textstream.h"
#include "morm.h"
@ -77,17 +78,28 @@ public:
TYPE_FUNCTION,
TYPE_DATE,
TYPE_MODEL,
TYPE_MODEL_CONTAINER_WRAPPER,
TYPE_SPACE_WRAPPER, // or just type_space
};
Type type;
Var();
Var(const Var & var);
Var & operator=(const Var & var);
~Var();
// IMPROVEME add move cctor and operator=
Var * add_child(const std::wstring & child_name, const Var & var);
Var * find_child(const std::wstring & child_name);
bool has_object();
bool has_model_object();
void clear();
void clear_childs();
bool to_bool() const;
@ -120,9 +132,12 @@ public:
void set(UserFunction user_function);
void set(const pt::Date & date);
// this model is not copied, is it a correct interface?
void set(morm::Model & model);
void set(morm::ModelContainerWrapper & model_container_wrapper);
@ -158,6 +173,8 @@ public:
Var & operator<<(const pt::Stream & str);
Type type;
UserFunction user_function;
morm::Model * model;
morm::ModelContainerWrapper * model_container_wrapper;
@ -169,6 +186,11 @@ public:
private:
std::map<std::wstring, Var> childs_map;
void initialize_empty();
void copy(const Var & var);
bool is_equal_bool(const char * str) const;
bool is_equal_string(const char * str) const;
@ -199,25 +221,148 @@ private:
template<typename StreamType>
Var<StreamType>::Var()
{
initialize_empty();
}
template<typename StreamType>
Var<StreamType>::Var(const Var & var)
{
initialize_empty();
copy(var);
}
template<typename StreamType>
Var<StreamType> & Var<StreamType>::operator=(const Var & var)
{
clear();
copy(var);
return *this;
}
template<typename StreamType>
void Var<StreamType>::copy(const Var & var)
{
type = var.type;
user_function = var.user_function;
model = var.model;
model_container_wrapper = var.model_container_wrapper;
date = var.date;
space_wrapper = var.space_wrapper;
space_local = var.space_local;
stream = var.stream;
if( model_container_wrapper )
{
model_container_wrapper->increment_reference_counter();
}
if( space_wrapper )
{
space_wrapper->increment_reference_counter();
}
// childs_map don't need to be copied
}
template<typename StreamType>
Var<StreamType>::~Var()
{
clear();
}
template<typename StreamType>
void Var<StreamType>::clear()
void Var<StreamType>::initialize_empty()
{
//res = false;
//is_function = false;
type = TYPE_VOID;
user_function = nullptr;
model = nullptr;
model_container_wrapper = nullptr;
date = nullptr;
space_wrapper = nullptr;
}
template<typename StreamType>
void Var<StreamType>::clear()
{
if( model_container_wrapper )
{
model_container_wrapper->decrement_reference_counter();
if( model_container_wrapper->get_reference_counter() == 0 && model_container_wrapper->should_be_auto_removed() )
{
delete model_container_wrapper;
}
}
if( space_wrapper )
{
space_wrapper->decrement_reference_counter();
if( space_wrapper->get_reference_counter() == 0 && space_wrapper->should_be_auto_removed() )
{
delete space_wrapper;
}
}
initialize_empty();
space_local.clear();
stream.clear();
clear_childs();
}
template<typename StreamType>
void Var<StreamType>::clear_childs()
{
childs_map.clear();
}
template<typename StreamType>
Var<StreamType> * Var<StreamType>::add_child(const std::wstring & child_name, const Var & var)
{
Var & v = childs_map[child_name];
v.clear();
v = var;
return &v;
}
template<typename StreamType>
Var<StreamType> * Var<StreamType>::find_child(const std::wstring & child_name)
{
auto i = childs_map.find(child_name);
if( i != childs_map.end() )
{
return &i->second;
}
return nullptr;
}
template<typename StreamType>
bool Var<StreamType>::has_object()
{
return type != TYPE_VOID;
}
template<typename StreamType>
bool Var<StreamType>::has_model_object()
{
return model || model_container_wrapper;
}
@ -238,6 +383,7 @@ bool Var<StreamType>::to_bool() const
case TYPE_STREAM:
case TYPE_FUNCTION:
case TYPE_DATE:
case TYPE_MODEL:
case TYPE_MODEL_CONTAINER_WRAPPER:
case TYPE_SPACE_WRAPPER:
@ -413,6 +559,14 @@ void Var<StreamType>::set(UserFunction user_function)
}
template<typename StreamType>
void Var<StreamType>::set(const pt::Date & date)
{
type = TYPE_DATE;
this->date = &date;
}
template<typename StreamType>
void Var<StreamType>::set(morm::Model & model)
{
@ -421,6 +575,14 @@ void Var<StreamType>::set(morm::Model & model)
}
template<typename StreamType>
void Var<StreamType>::set(morm::ModelContainerWrapper & model_container_wrapper)
{
type = TYPE_MODEL_CONTAINER_WRAPPER;
this->model_container_wrapper = &model_container_wrapper;
}
template<typename StreamType>
bool Var<StreamType>::is_equal(const char * str) const
@ -438,6 +600,7 @@ bool Var<StreamType>::is_equal(const char * str) const
case TYPE_DOUBLE:
case TYPE_STREAM:
case TYPE_FUNCTION:
case TYPE_DATE:
case TYPE_MODEL:
case TYPE_MODEL_CONTAINER_WRAPPER:
case TYPE_SPACE_WRAPPER:
@ -465,6 +628,7 @@ bool Var<StreamType>::is_equal(const wchar_t * str) const
case TYPE_DOUBLE:
case TYPE_STREAM:
case TYPE_FUNCTION:
case TYPE_DATE:
case TYPE_MODEL:
case TYPE_MODEL_CONTAINER_WRAPPER:
case TYPE_SPACE_WRAPPER:
@ -573,6 +737,10 @@ void Var<StreamType>::serialize_to(pt::WTextStream & str)
str = stream;
break;
case TYPE_DATE:
date->SerializeISO(str);
break;
case TYPE_VOID:
case TYPE_FUNCTION:
case TYPE_MODEL: