From e6fd9aad3702d1a3859b39914758eb40c9ed9d29 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Mon, 31 May 2021 18:37:09 +0200 Subject: [PATCH] added basic support for calling variables and functions from morm::Model objects --- src/Makefile.dep | 55 +++++++++++++- src/Makefile.o.dep | 2 +- src/generator.h | 165 +++++++++++++++++++++++++++++++++++++++--- src/item.h | 2 + src/models.cpp | 79 ++++++++++++++++++++ src/models.h | 72 ++++++++++++++++++ src/patternparser.cpp | 31 ++++++-- src/patternparser.h | 1 + 8 files changed, 384 insertions(+), 23 deletions(-) create mode 100644 src/models.cpp create mode 100644 src/models.h diff --git a/src/Makefile.dep b/src/Makefile.dep index 1bcb86d..d895b63 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -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 diff --git a/src/Makefile.o.dep b/src/Makefile.o.dep index 0bd4ba5..2f6a2c4 100644 --- a/src/Makefile.o.dep +++ b/src/Makefile.o.dep @@ -1 +1 @@ -o = blocks.o cache.o item.o pattern.o patternparser.o \ No newline at end of file +o = blocks.o cache.o item.o models.o pattern.o patternparser.o \ No newline at end of file diff --git a/src/generator.h b/src/generator.h index 9b49ed8..e021a90 100644 --- a/src/generator.h +++ b/src/generator.h @@ -39,15 +39,16 @@ #ifndef headerfile_ezc_generator #define headerfile_ezc_generator +#include +#include +#include #include "blocks.h" #include "pattern.h" #include "functions.h" #include "objects.h" #include "outstreams.h" -#include -#include -#include #include "expressionparser.h" +#include "models.h" namespace Ezc @@ -74,7 +75,7 @@ public: void SetFunctions(Functions & functions); void SetObjects(Objects & 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 * pfunctions; Objects * pobjects; + Models * pmodels; Vars * pvars; // pointer to the output streams map (can be null) @@ -244,6 +246,8 @@ private: typename Functions::UserFunction ** function, Item ** item_block); + bool FindInModels(const std::wstring & name, morm::Model ** model); + bool FindInFunctionsAndBlocks(const std::wstring & name, BaseObj ** base_obj, int * method_index, @@ -274,9 +278,9 @@ private: std::vector & parameters, StreamType & out_stream); - void CallObject(BaseObj * base_obj, int method_index, FunInfo & info); + void CallModel(morm::Model & model, std::vector & fields, std::vector parameters, StreamType & out_stream, const StreamType & in_stream); void CallObject(BaseObj * 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 parameters); void CopyTmpStreamToOutputStreams(Item::Function & fun, StreamType & ezc_out_tmp_stream, StreamType & previous_stream); @@ -351,11 +357,12 @@ private: template Generator::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 & Generator::operator=(const Generator::SetVariables(Vars & variables) } +template +void Generator::SetModels(Models & models) +{ + pmodels = ⊧ +} + + template void Generator::CanUseCache(bool can_use_cache) { @@ -875,6 +890,28 @@ return false; + +template +bool Generator::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 bool Generator::FindInFunctionsAndBlocks(const std::wstring & name, BaseObj ** base_obj, @@ -1043,6 +1080,99 @@ void Generator::CallObject(BaseObj * base_obj, int metho +template +void Generator::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 +bool Generator::ShouldEscapeValue(std::vector parameters) +{ + for(Var & var : parameters) + { + if( !var.is_function ) + { + if( var.str == L"raw" || var.str == L"noescape" ) + { + return false; + } + } + } + + return true; +} + + + + +template +void Generator::CallModel(morm::Model & model, std::vector & fields, std::vector 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 ; iget_field_model(field.c_str(), field.c_str()); + + if( !m ) + { + // put some log + break; + } + } + else + { + // last field + pt::TextStream str; + + if( parameters.empty() ) + { + FunInfo 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 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 void Generator::CallObject(BaseObj * base_obj, int method_index, @@ -1140,12 +1270,20 @@ typename Functions::UserFunction * fun; Item * item_block; Var * variable; std::vector 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 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 diff --git a/src/item.h b/src/item.h index 90f2d82..3e5ce13 100644 --- a/src/item.h +++ b/src/item.h @@ -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 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 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 + */ + +/* + * 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(); +} + + + + +} + + diff --git a/src/models.h b/src/models.h new file mode 100644 index 0000000..a5dc030 --- /dev/null +++ b/src/models.h @@ -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 + */ + +/* + * 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 +#include + +// 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 models_map; + +}; + +} + + +#endif + diff --git a/src/patternparser.cpp b/src/patternparser.cpp index cab0b0d..aed1e2d 100644 --- a/src/patternparser.cpp +++ b/src/patternparser.cpp @@ -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); + } } } diff --git a/src/patternparser.h b/src/patternparser.h index 037d357..f2906e8 100644 --- a/src/patternparser.h +++ b/src/patternparser.h @@ -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);