added basic support for calling variables and functions from morm::Model objects

This commit is contained in:
2021-05-31 18:37:09 +02:00
parent 052f803eac
commit e6fd9aad37
8 changed files with 384 additions and 23 deletions

View File

@@ -39,15 +39,16 @@
#ifndef headerfile_ezc_generator
#define headerfile_ezc_generator
#include <sstream>
#include <fstream>
#include <vector>
#include "blocks.h"
#include "pattern.h"
#include "functions.h"
#include "objects.h"
#include "outstreams.h"
#include <sstream>
#include <fstream>
#include <vector>
#include "expressionparser.h"
#include "models.h"
namespace Ezc
@@ -74,7 +75,7 @@ public:
void SetFunctions(Functions<StreamType> & functions);
void SetObjects(Objects<StreamType> & objects);
void SetVariables(Vars & variables); // [def] and [let]
void SetModels(Models & models);
void SetMax(size_t max_items_, size_t max_for_items_);
@@ -151,6 +152,7 @@ private:
Blocks * pblocks;
Functions<StreamType> * pfunctions;
Objects<StreamType> * pobjects;
Models * pmodels;
Vars * pvars;
// pointer to the output streams map (can be null)
@@ -244,6 +246,8 @@ private:
typename Functions<StreamType>::UserFunction ** function,
Item ** item_block);
bool FindInModels(const std::wstring & name, morm::Model ** model);
bool FindInFunctionsAndBlocks(const std::wstring & name,
BaseObj<StreamType> ** base_obj,
int * method_index,
@@ -274,9 +278,9 @@ private:
std::vector<Var> & parameters,
StreamType & out_stream);
void CallObject(BaseObj<StreamType> * base_obj, int method_index, FunInfo<StreamType> & info);
void CallModel(morm::Model & model, std::vector<std::wstring> & fields, std::vector<Var> parameters, StreamType & out_stream, const StreamType & in_stream);
void CallObject(BaseObj<StreamType> * base_obj,
int method_index,
@@ -306,6 +310,8 @@ private:
void TrimWhite(const wchar_t *& start, const wchar_t *& end);
void SkipWhite(const wchar_t *& str);
size_t StrToSize(const wchar_t * str, const wchar_t ** str_end = 0);
void CopyStream(pt::TextStream src_stream, StreamType & dst_stream, bool should_escape);
bool ShouldEscapeValue(std::vector<Var> parameters);
void CopyTmpStreamToOutputStreams(Item::Function & fun, StreamType & ezc_out_tmp_stream, StreamType & previous_stream);
@@ -351,11 +357,12 @@ private:
template<class StreamType>
Generator<StreamType>::Generator() : empty_stream()
{
ppattern = 0;
pblocks = 0;
pfunctions = 0;
pobjects = 0;
pvars = 0;
ppattern = nullptr;
pblocks = nullptr;
pfunctions = nullptr;
pobjects = nullptr;
pvars = nullptr;
pmodels = nullptr;
max_items = 50000;
max_for_items = 5000;
@@ -390,6 +397,7 @@ Generator<StreamType> & Generator<StreamType>::operator=(const Generator<StreamT
pfunctions = n.pfunctions;
pobjects = n.pobjects;
pvars = n.pvars;
pmodels = n.pmodels;
max_items = n.max_items;
max_for_items = n.max_for_items;
@@ -507,6 +515,13 @@ void Generator<StreamType>::SetVariables(Vars & variables)
}
template<class StreamType>
void Generator<StreamType>::SetModels(Models & models)
{
pmodels = &models;
}
template<class StreamType>
void Generator<StreamType>::CanUseCache(bool can_use_cache)
{
@@ -875,6 +890,28 @@ return false;
template<class StreamType>
bool Generator<StreamType>::FindInModels(const std::wstring & name, morm::Model ** model)
{
*model = nullptr;
if( pmodels )
{
morm::Model * m = pmodels->Find(name);
if( m )
{
*model = m;
return true;
}
}
return false;
}
template<class StreamType>
bool Generator<StreamType>::FindInFunctionsAndBlocks(const std::wstring & name,
BaseObj<StreamType> ** base_obj,
@@ -1043,6 +1080,99 @@ void Generator<StreamType>::CallObject(BaseObj<StreamType> * base_obj, int metho
template<class StreamType>
void Generator<StreamType>::CopyStream(pt::TextStream src_stream, StreamType & dst_stream, bool should_escape)
{
pt::TextStream::iterator i = src_stream.begin();
while( i != src_stream.end() )
{
if( should_escape )
{
dst_stream << *i;
}
else
{
dst_stream.write(&(*i), 1);
}
++i;
}
}
template<class StreamType>
bool Generator<StreamType>::ShouldEscapeValue(std::vector<Var> parameters)
{
for(Var & var : parameters)
{
if( !var.is_function )
{
if( var.str == L"raw" || var.str == L"noescape" )
{
return false;
}
}
}
return true;
}
template<class StreamType>
void Generator<StreamType>::CallModel(morm::Model & model, std::vector<std::wstring> & fields, std::vector<Var> parameters, StreamType & out_stream, const StreamType & in_stream)
{
bool should_escape = ShouldEscapeValue(parameters);
if( fields.empty() )
{
pt::TextStream str;
model.to_text(str, false, false);
CopyStream(str, out_stream, should_escape);
}
else
{
morm::Model * m = &model;
for(size_t i=0 ; i<fields.size() ; ++i)
{
std::wstring & field = fields[i];
if( i+1 < fields.size() )
{
m = m->get_field_model(field.c_str(), field.c_str());
if( !m )
{
// put some log
break;
}
}
else
{
// last field
pt::TextStream str;
if( parameters.empty() )
{
FunInfo<StreamType> info(out_stream, parameters, empty, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item);
m->put_field_value(field.c_str(), nullptr, info, str, false);
}
else
{
FunInfo<StreamType> info(out_stream, parameters, parameters[0].str, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item);
m->put_field_value(field.c_str(), nullptr, info, str, false);
}
CopyStream(str, out_stream, should_escape);
}
}
}
}
template<class StreamType>
void Generator<StreamType>::CallObject(BaseObj<StreamType> * base_obj,
int method_index,
@@ -1140,12 +1270,20 @@ typename Functions<StreamType>::UserFunction * fun;
Item * item_block;
Var * variable;
std::vector<Var> parameters;
morm::Model * model;
if( clear_out_stream )
ClearStream(out_stream);
if( !Find(item_fun, fun_name, &base_obj, &method_index, &fun, &item_block, &variable) )
return false;
if( !fun_name )
fun_name = &item_fun.name;
// add macro
if( !FindInModels(*fun_name, &model) )
{
if( !Find(item_fun, fun_name, &base_obj, &method_index, &fun, &item_block, &variable) )
return false;
}
parameters.resize(item_fun.parameters.size());
@@ -1173,6 +1311,9 @@ std::vector<Var> parameters;
}
}
if( model )
CallModel(*model, item_fun.fields, parameters, out_stream, in_stream);
else
if( base_obj )
CallObject(base_obj, method_index, parameters, out_stream, in_stream);
else