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

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

View File

@ -1,8 +1,55 @@
# DO NOT DELETE
blocks.o: blocks.h item.h cache.h functions.h funinfo.h objects.h
cache.o: cache.h item.h functions.h funinfo.h objects.h blocks.h
blocks.o: blocks.h item.h cache.h functions.h ../../pikotools/src/utf8/utf8.h
blocks.o: ../../pikotools/src/textstream/textstream.h
blocks.o: ../../pikotools/src/space/space.h
blocks.o: ../../pikotools/src/textstream/types.h
blocks.o: ../../pikotools/src/convert/inttostr.h
blocks.o: ../../pikotools/src/date/date.h
blocks.o: ../../pikotools/src/membuffer/membuffer.h
blocks.o: ../../pikotools/src/textstream/types.h
blocks.o: ../../pikotools/src/utf8/utf8_templates.h
blocks.o: ../../pikotools/src/utf8/utf8_private.h funinfo.h objects.h
cache.o: cache.h item.h functions.h ../../pikotools/src/utf8/utf8.h
cache.o: ../../pikotools/src/textstream/textstream.h
cache.o: ../../pikotools/src/space/space.h
cache.o: ../../pikotools/src/textstream/types.h
cache.o: ../../pikotools/src/convert/inttostr.h
cache.o: ../../pikotools/src/date/date.h
cache.o: ../../pikotools/src/membuffer/membuffer.h
cache.o: ../../pikotools/src/textstream/types.h
cache.o: ../../pikotools/src/utf8/utf8_templates.h
cache.o: ../../pikotools/src/utf8/utf8_private.h funinfo.h objects.h blocks.h
item.o: item.h
pattern.o: pattern.h item.h cache.h functions.h funinfo.h objects.h blocks.h
models.o: models.h
pattern.o: pattern.h item.h cache.h functions.h
pattern.o: ../../pikotools/src/utf8/utf8.h
pattern.o: ../../pikotools/src/textstream/textstream.h
pattern.o: ../../pikotools/src/space/space.h
pattern.o: ../../pikotools/src/textstream/types.h
pattern.o: ../../pikotools/src/convert/inttostr.h
pattern.o: ../../pikotools/src/date/date.h
pattern.o: ../../pikotools/src/membuffer/membuffer.h
pattern.o: ../../pikotools/src/textstream/types.h
pattern.o: ../../pikotools/src/utf8/utf8_templates.h
pattern.o: ../../pikotools/src/utf8/utf8_private.h funinfo.h objects.h
pattern.o: blocks.h
patternparser.o: patternparser.h blocks.h item.h cache.h functions.h
patternparser.o: funinfo.h objects.h pattern.h
patternparser.o: ../../pikotools/src/utf8/utf8.h
patternparser.o: ../../pikotools/src/textstream/textstream.h
patternparser.o: ../../pikotools/src/space/space.h
patternparser.o: ../../pikotools/src/textstream/types.h
patternparser.o: ../../pikotools/src/convert/inttostr.h
patternparser.o: ../../pikotools/src/date/date.h
patternparser.o: ../../pikotools/src/membuffer/membuffer.h
patternparser.o: ../../pikotools/src/textstream/types.h
patternparser.o: ../../pikotools/src/utf8/utf8_templates.h
patternparser.o: ../../pikotools/src/utf8/utf8_private.h funinfo.h objects.h
patternparser.o: pattern.h ../../pikotools/src/log/log.h
patternparser.o: ../../pikotools/src/log/filelog.h
patternparser.o: ../../pikotools/src/convert/convert.h
patternparser.o: ../../pikotools/src/convert/inttostr.h
patternparser.o: ../../pikotools/src/convert/patternreplacer.h
patternparser.o: ../../pikotools/src/convert/strtoint.h
patternparser.o: ../../pikotools/src/convert/text.h
patternparser.o: ../../pikotools/src/convert/misc.h

View File

@ -1 +1 @@
o = blocks.o cache.o item.o pattern.o patternparser.o
o = blocks.o cache.o item.o models.o pattern.o patternparser.o

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

View File

@ -64,6 +64,7 @@ struct Item
{
bool is_function; // if true then we have a function parameter, if false then we have a string parameter
std::wstring name; // a function or parameter name
std::vector<std::wstring> fields; // any number of additional fields after a dot e.g. [name.field1.field2]
std::wstring postfix; // a function can have an additional postfix in its name
// e.g. [my_function:my_postfix]
std::vector<Function*> parameters; // if is_function is true then it is a function and can have 'parameters'
@ -123,6 +124,7 @@ struct Item
for(size_t i=0 ; i<parameters.size() ; ++i)
delete parameters[i];
fields.clear();
parameters.clear();
name.clear();
postfix.clear();

79
src/models.cpp Normal file
View File

@ -0,0 +1,79 @@
/*
* This file is a part of EZC -- Easy templating in C++ library
* and is distributed under the BSD 3-Clause licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2021, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "models.h"
namespace Ezc
{
void Models::Add(const std::wstring & name, morm::Model & model)
{
models_map[name] = &model;
}
void Models::Add(const std::wstring & name, morm::Model * model)
{
models_map[name] = model;
}
morm::Model * Models::Find(const std::wstring & name)
{
auto iterator = models_map.find(name);
if( iterator != models_map.end() )
{
return iterator->second;
}
return nullptr;
}
void Models::Clear()
{
models_map.clear();
}
}

72
src/models.h Normal file
View File

@ -0,0 +1,72 @@
/*
* This file is a part of EZC -- Easy templating in C++ library
* and is distributed under the BSD 3-Clause licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2021, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name Tomasz Sowa nor the names of contributors to this
* project may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef headerfile_ezc_models
#define headerfile_ezc_models
#include <map>
#include <string>
// put some macros
#include "model.h"
namespace Ezc
{
class Models
{
public:
void Add(const std::wstring & name, morm::Model & model);
void Add(const std::wstring & name, morm::Model * model);
morm::Model * Find(const std::wstring & name);
void Clear();
protected:
std::map<std::wstring, morm::Model*> models_map;
};
}
#endif

View File

@ -486,7 +486,7 @@ bool PatternParser::IsNameChar(wchar_t c)
return ((c>='a' && c<='z') ||
(c>='A' && c<='Z') ||
(c>='0' && c<='9') ||
c=='_' || c=='-' || c=='.' || c=='#' || c=='?');
c=='_' || c=='-' || c=='#' || c=='?');
}
@ -622,7 +622,28 @@ return res;
}
void PatternParser::ReadFunctionFields(Item::Function & function)
{
std::wstring field;
bool read_next_field = true;
while( *itext == '.' && read_next_field )
{
itext += 1;
read_next_field = ReadName(field);
if( read_next_field )
{
function.fields.emplace_back(field);
}
}
if( *itext == ':' )
{
itext += 1;
ReadName(function.postfix); // we allow the postfix to be empty
}
}
bool PatternParser::ReadFunction(Item::Function & function, bool with_params)
@ -654,14 +675,12 @@ bool PatternParser::ReadFunction(Item::Function & function, bool with_params)
if( res )
{
if( *itext == ':' )
{
itext += 1;
ReadName(function.postfix); // we allow the postfix to be empty
}
ReadFunctionFields(function);
if( with_params )
{
res = ReadParams(function);
}
}
}

View File

@ -165,6 +165,7 @@ private:
bool ReadString(std::wstring & str);
bool ReadParamString(Item::Function & function);
bool ReadParams(Item::Function & function);
void ReadFunctionFields(Item::Function & function);
bool ReadFunction(Item::Function & function, bool with_params);
bool ReadFunction(Item & item);