From e6fd9aad3702d1a3859b39914758eb40c9ed9d29 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Mon, 31 May 2021 18:37:09 +0200 Subject: [PATCH 01/19] 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); From 9022d4a5fce1d184a368356710bbd50ba46f5ab7 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Wed, 16 Jun 2021 14:16:49 +0200 Subject: [PATCH 02/19] changed how models from morm library are used now we are using morm::ModelWrapper... classes as wrappers on models and list/vector of models and Models class is using these wrappers this allows us to iterate through list/vectors in [for...] statements --- src/Makefile.dep | 27 +--- src/generator.h | 401 ++++++++++++++++++++++++++++++----------------- src/models.cpp | 49 ++++-- src/models.h | 46 +++++- 4 files changed, 339 insertions(+), 184 deletions(-) diff --git a/src/Makefile.dep b/src/Makefile.dep index d895b63..328b1be 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -1,41 +1,23 @@ # DO NOT DELETE 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 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: ../../pikotools/src/utf8/utf8.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/textstream/textstream.h patternparser.o: ../../pikotools/src/space/space.h patternparser.o: ../../pikotools/src/textstream/types.h @@ -43,9 +25,6 @@ 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 diff --git a/src/generator.h b/src/generator.h index e021a90..4f61a05 100644 --- a/src/generator.h +++ b/src/generator.h @@ -50,6 +50,9 @@ #include "expressionparser.h" #include "models.h" +#ifdef EZC_HAS_MORM_LIBRARY +#include "model.h" +#endif namespace Ezc { @@ -75,7 +78,10 @@ public: void SetFunctions(Functions & functions); void SetObjects(Objects & objects); void SetVariables(Vars & variables); // [def] and [let] + +#ifdef EZC_HAS_MORM_LIBRARY void SetModels(Models & models); +#endif void SetMax(size_t max_items_, size_t max_for_items_); @@ -133,6 +139,53 @@ public: private: + struct FindHelper + { + #ifdef EZC_HAS_MORM_LIBRARY + morm::ModelWrapper * model_wrapper; + #endif + + BaseObj * base_obj; + int method_index; + typename Functions::UserFunction * function; + Item * item_block; + Var * variable; + + + FindHelper() + { + #ifdef EZC_HAS_MORM_LIBRARY + model_wrapper = nullptr; + #endif + base_obj = nullptr; + method_index = -1; + function = nullptr; + item_block = nullptr; + variable = nullptr; + } + }; + + +#ifdef EZC_HAS_MORM_LIBRARY + + struct CallModelHelper + { + size_t field_index; + morm::ModelWrapper * model_wrapper; + morm::Model * model; + + + CallModelHelper() + { + field_index = 0; + model_wrapper = nullptr; + model = nullptr; + } + }; + +#endif + + struct BlockStack { std::vector args; @@ -152,7 +205,9 @@ private: Blocks * pblocks; Functions * pfunctions; Objects * pobjects; +#ifdef EZC_HAS_MORM_LIBRARY Models * pmodels; +#endif Vars * pvars; // pointer to the output streams map (can be null) @@ -238,38 +293,25 @@ private: CharType ToLower(CharType c); - bool CheckBlockArgument(int arg_index, Var ** variable); + bool CheckBlockArgument(int arg_index, FindHelper & find_helper); - bool FindInCache(Item::Function & item_fun, - BaseObj ** base_obj, - int * method_index, - typename Functions::UserFunction ** function, - Item ** item_block); + bool FindInCache(Item::Function & item_fun, FindHelper & find_helper); - bool FindInModels(const std::wstring & name, morm::Model ** model); +#ifdef EZC_HAS_MORM_LIBRARY + bool FindInModels(const std::wstring & name, FindHelper & find_helper); +#endif - bool FindInFunctionsAndBlocks(const std::wstring & name, - BaseObj ** base_obj, - int * method_index, - typename Functions::UserFunction ** function, - Item ** item_block); + bool FindInFunctionsAndBlocks(const std::wstring & name, FindHelper & find_helper); - bool FindInVariables(const std::wstring & name, - Var ** variable); - + bool FindInVariables(const std::wstring & name, FindHelper & find_helper); bool Find(Item::Function & item_fun, - std::wstring * fun_name, - BaseObj ** base_obj, - int * method_index, - typename Functions::UserFunction ** function, - Item ** item_block, - Var ** variable); + std::wstring & fun_name, + FindHelper & find_helper); - void CallFunction(typename Functions::UserFunction * function, - FunInfo & info); + void CallFunction(typename Functions::UserFunction & function, FunInfo & info); - void CallFunction(typename Functions::UserFunction * function, + void CallFunction(typename Functions::UserFunction & function, std::vector & parameters, StreamType & out_stream, const StreamType & in_stream); @@ -278,18 +320,22 @@ private: std::vector & parameters, StreamType & out_stream); - void CallObject(BaseObj * base_obj, int method_index, FunInfo & info); + 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); +#ifdef EZC_HAS_MORM_LIBRARY + void CallModel(morm::Model & model, const std::wstring & field, std::vector parameters, StreamType & out_stream, const StreamType & in_stream); + CallModelHelper FindLastModelWrapper(morm::ModelWrapper & models_base, std::vector & fields); + void CallModelWrapper(morm::ModelWrapper & models_base, std::vector & fields, std::vector parameters, StreamType & out_stream, const StreamType & in_stream); +#endif - void CallObject(BaseObj * base_obj, + void CallObject(BaseObj & base_obj, int method_index, std::vector & parameters, StreamType & out_stream, const StreamType & in_stream); bool CallVariable(Item::Function & item_fun, - Var * variable, + Var & variable, std::vector & parameters, StreamType & out_stream, const StreamType & in_stream); @@ -362,7 +408,10 @@ Generator::Generator() : empty_stream() pfunctions = nullptr; pobjects = nullptr; pvars = nullptr; + +#ifdef EZC_HAS_MORM_LIBRARY pmodels = nullptr; +#endif max_items = 50000; max_for_items = 5000; @@ -397,7 +446,10 @@ Generator & Generator::operator=(const Generator::SetVariables(Vars & variables) } +#ifdef EZC_HAS_MORM_LIBRARY template void Generator::SetModels(Models & models) { pmodels = ⊧ } - +#endif template void Generator::CanUseCache(bool can_use_cache) @@ -834,7 +887,7 @@ void Generator::Generate(OutStreams & out_streams) template -bool Generator::CheckBlockArgument(int arg_index, Var ** variable) +bool Generator::CheckBlockArgument(int arg_index, FindHelper & find_helper) { if( arg_index < 0 ) return false; @@ -846,7 +899,7 @@ bool Generator::CheckBlockArgument(int arg_index, Var ** variable) if( size_t(arg_index) < block_stack.args.size() ) { - *variable = &block_stack.args[arg_index]; + find_helper.variable = &block_stack.args[arg_index]; return true; } } @@ -857,30 +910,26 @@ bool Generator::CheckBlockArgument(int arg_index, Var ** variable) template -bool Generator::FindInCache(Item::Function & item_fun, - BaseObj ** base_obj, - int * method_index, - typename Functions::UserFunction ** function, - Item ** item_block) +bool Generator::FindInCache(Item::Function & item_fun, FindHelper & find_helper) { if( can_find_in_cache ) { if( item_fun.base_obj ) { - *base_obj = reinterpret_cast * >(item_fun.base_obj); - *method_index = item_fun.method_index; + find_helper.base_obj = reinterpret_cast * >(item_fun.base_obj); + find_helper.method_index = item_fun.method_index; return true; } if( item_fun.fun_cache ) { - *function = reinterpret_cast::UserFunction*>(item_fun.fun_cache); + find_helper.function = reinterpret_cast::UserFunction*>(item_fun.fun_cache); return true; } if( item_fun.item_block ) { - *item_block = item_fun.item_block; + find_helper.item_block = item_fun.item_block; return true; } } @@ -890,19 +939,18 @@ return false; +#ifdef EZC_HAS_MORM_LIBRARY template -bool Generator::FindInModels(const std::wstring & name, morm::Model ** model) +bool Generator::FindInModels(const std::wstring & name, FindHelper & find_helper) { - *model = nullptr; - if( pmodels ) { - morm::Model * m = pmodels->Find(name); + morm::ModelWrapper * m = pmodels->Find(name); if( m ) { - *model = m; + find_helper.model_wrapper = m; return true; } } @@ -910,22 +958,19 @@ bool Generator::FindInModels(const std::wstring & name, morm::Model return false; } +#endif template -bool Generator::FindInFunctionsAndBlocks(const std::wstring & name, - BaseObj ** base_obj, - int * method_index, - typename Functions::UserFunction ** function, - Item ** item_block) +bool Generator::FindInFunctionsAndBlocks(const std::wstring & name, FindHelper & find_helper) { if( pobjects ) { - typename Objects::Iterator i = pobjects->Find(name, *method_index); + typename Objects::Iterator i = pobjects->Find(name, find_helper.method_index); if( i != pobjects->End() ) { - *base_obj = *i; + find_helper.base_obj = *i; return true; } } @@ -936,7 +981,7 @@ bool Generator::FindInFunctionsAndBlocks(const std::wstring & name, if( i != pfunctions->End() ) { - *function = &i->second; + find_helper.function = &i->second; return true; } } @@ -947,7 +992,7 @@ bool Generator::FindInFunctionsAndBlocks(const std::wstring & name, if( i != pblocks->End() ) { - *item_block = &i->second; + find_helper.item_block = &i->second; return true; } } @@ -957,8 +1002,7 @@ return false; template -bool Generator::FindInVariables(const std::wstring & name, - Var ** variable) +bool Generator::FindInVariables(const std::wstring & name, FindHelper & find_helper) { if( pvars ) { @@ -966,7 +1010,7 @@ bool Generator::FindInVariables(const std::wstring & name, if( i != pvars->end() ) { - *variable = &(i->second); + find_helper.variable = &(i->second); return true; } } @@ -975,49 +1019,41 @@ bool Generator::FindInVariables(const std::wstring & name, } + /* * fun_name can be null, it is used only with [let ...] statements * and if not null then means: as a funcion name we are not using item_fun.name but fun_name */ template bool Generator::Find(Item::Function & item_fun, - std::wstring * fun_name, - BaseObj ** base_obj, - int * method_index, - typename Functions::UserFunction ** function, - Item ** item_block, - Var ** variable) + std::wstring & fun_name, + FindHelper & find_helper) { - *base_obj = nullptr; - *method_index = -1; - *function = nullptr; - *item_block = nullptr; - *variable = nullptr; + #ifdef EZC_HAS_MORM_LIBRARY + if( FindInModels(fun_name, find_helper) ) + return true; + #endif - if( CheckBlockArgument(item_fun.arg, variable) ) + if( CheckBlockArgument(item_fun.arg, find_helper) ) return true; - if( FindInCache(item_fun, base_obj, method_index, function, item_block) ) + if( FindInCache(item_fun, find_helper) ) return true; - if( !fun_name ) - fun_name = &item_fun.name; - - if( FindInFunctionsAndBlocks(*fun_name, base_obj, method_index, function, item_block) ) + if( FindInFunctionsAndBlocks(fun_name, find_helper) ) return true; - if( FindInVariables(*fun_name, variable) ) + if( FindInVariables(fun_name, find_helper) ) return true; - CreateUnknownMsg(*fun_name); - -return false; + CreateUnknownMsg(fun_name); + return false; } template -void Generator::CallFunction(typename Functions::UserFunction * function, FunInfo & info) +void Generator::CallFunction(typename Functions::UserFunction & function, FunInfo & info) { info.Clear(); @@ -1026,10 +1062,10 @@ void Generator::CallFunction(typename Functions::UserFun info.is_normal = is_generating_normal; info.is_filter = is_generating_filter; info.iter = info.stack.iter; - info.stack_tab = &stack_tab[0];//stack_tab.data();///////////////////////////////////////////////////////// + info.stack_tab = stack_tab.data(); info.stack_index = stack_index-1; - (*function)(info); + (function)(info); last_res = info.res; } @@ -1037,7 +1073,7 @@ void Generator::CallFunction(typename Functions::UserFun template -void Generator::CallFunction(typename Functions::UserFunction * function, +void Generator::CallFunction(typename Functions::UserFunction & function, std::vector & parameters, StreamType & out_stream, const StreamType & in_stream) @@ -1061,7 +1097,7 @@ void Generator::CallFunction(typename Functions::UserFun template -void Generator::CallObject(BaseObj * base_obj, int method_index, FunInfo & info) +void Generator::CallObject(BaseObj & base_obj, int method_index, FunInfo & info) { info.Clear(); @@ -1070,10 +1106,10 @@ void Generator::CallObject(BaseObj * base_obj, int metho info.is_normal = is_generating_normal; info.is_filter = is_generating_filter; info.iter = info.stack.iter; - info.stack_tab = &stack_tab[0];//stack_tab.data();///////////////////////////////////////////////////////// + info.stack_tab = stack_tab.data(); info.stack_index = stack_index-1; - base_obj->CallFun(method_index, info); + base_obj.CallFun(method_index, info); last_res = info.res; } @@ -1093,7 +1129,15 @@ void Generator::CopyStream(pt::TextStream src_stream, StreamType & d } else { - dst_stream.write(&(*i), 1); + if constexpr(sizeof(pt::TextStream::char_type) == sizeof(typename StreamType::char_type)) + { + dst_stream.write(&(*i), 1); + } + else + { + wchar_t buf = static_cast(*i); + dst_stream.write(&buf, 1); + } } ++i; @@ -1121,60 +1165,136 @@ bool Generator::ShouldEscapeValue(std::vector parameters) +#ifdef EZC_HAS_MORM_LIBRARY template -void Generator::CallModel(morm::Model & model, std::vector & fields, std::vector parameters, StreamType & out_stream, const StreamType & in_stream) +void Generator::CallModel(morm::Model & model, const std::wstring & field, std::vector parameters, StreamType & out_stream, const StreamType & in_stream) { - bool should_escape = ShouldEscapeValue(parameters); + /* + * if 'field' is a POD type then 'str' will be used in get_raw_value() + * if 'field' is a getter method with pt::TextStream then 'str' will be used too + * if 'field' is a getter method which takes FunInfo<> then out_stream will be used and 'str' will be empty + * + */ + pt::TextStream str; - if( fields.empty() ) + if( parameters.empty() ) { - pt::TextStream str; - model.to_text(str, false, false); - CopyStream(str, out_stream, should_escape); + FunInfo info(out_stream, parameters, empty, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item); + model.get_raw_value(nullptr, field.c_str(), nullptr, info, str, false); + last_res = info.res; } else { - morm::Model * m = &model; + FunInfo info(out_stream, parameters, parameters[0].str, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item); + model.get_raw_value(nullptr, field.c_str(), nullptr, info, str, false); + last_res = info.res; + } - for(size_t i=0 ; i +Generator::CallModelHelper Generator::FindLastModelWrapper(morm::ModelWrapper & models_base, std::vector & fields) +{ + CallModelHelper helper; + helper.field_index = 0; + helper.model_wrapper = &models_base; + helper.model = nullptr; + + for(; helper.field_index < fields.size() ; ++helper.field_index) + { + std::wstring & field = fields[helper.field_index]; + morm::ModelWrapper * child_models_base = helper.model_wrapper->find_child(field); + + if( !child_models_base ) { - std::wstring & field = fields[i]; + helper.model = helper.model_wrapper->get_model(); + // this can return null for lists/vectors in a case when the iterator is not pointing to a valid item - if( i+1 < fields.size() ) + if( helper.model ) { - m = m->get_field_model(field.c_str(), field.c_str()); + child_models_base = helper.model->get_model_wrapper(nullptr, field.c_str(), false); - if( !m ) + if( child_models_base ) { - // put some log - break; + helper.model_wrapper->add_child(field, child_models_base); } } - 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); - } + if( !child_models_base ) + break; - CopyStream(str, out_stream, should_escape); - } + helper.model_wrapper = child_models_base; + helper.model = nullptr; + } + + return helper; +} + + +template +void Generator::CallModelWrapper(morm::ModelWrapper & models_base_root, std::vector & fields, + std::vector parameters, StreamType & out_stream, const StreamType & in_stream) +{ + last_res = false; + CallModelHelper helper = FindLastModelWrapper(models_base_root, fields); + + // if: + // helper.field_index == fields.size() - all fields items are models or models containers + // helper.field_index == fields.size()-1 - last field is not a model nor a models container + // helper.field_index < fields.size()-1 - incorrect + + if( helper.field_index + 1 < fields.size() ) + { + // put some log + // at the end there are some fields which are not models nor models containers + last_res = false; + return; + } + + if( helper.field_index + 1 == fields.size() ) + { + // last field is not a model nor a models container + + if( helper.model ) + { + CallModel(*helper.model, fields[helper.field_index], parameters, out_stream, in_stream); + } + else + { + last_res = false; + // put log something like: + // model not set, have you forgotten to use [for ...] statement? + } + } + else + { + // all fields items are models or models containers + // this is usualy in [for...] or [if ...] statements + // helper.model_wrapper is always set + if( stack_tab[stack_index-1].is_for ) + { + helper.model_wrapper->increment_iterator(); + helper.model_wrapper->clear_childs(); + last_res = helper.model_wrapper->is_iterator_correct(); + } + else + { + last_res = !helper.model_wrapper->is_container_empty(); } } } +#endif + + template -void Generator::CallObject(BaseObj * base_obj, +void Generator::CallObject(BaseObj & base_obj, int method_index, std::vector & parameters, StreamType & out_stream, @@ -1236,16 +1356,16 @@ return true; template -bool Generator::CallVariable(Item::Function & item_fun, Var * variable, std::vector & parameters, StreamType & out_stream, const StreamType & in_stream) +bool Generator::CallVariable(Item::Function & item_fun, Var & variable, std::vector & parameters, StreamType & out_stream, const StreamType & in_stream) { - if( variable->is_function ) + if( variable.is_function ) { - return Call(item_fun, &variable->str, out_stream, false, in_stream); + return Call(item_fun, &variable.str, out_stream, false, in_stream); } else { - out_stream << variable->str; - last_res = variable->res; + out_stream << variable.str; + last_res = variable.res; return true; } } @@ -1264,13 +1384,8 @@ bool Generator::Call(Item::Function & item_fun, bool clear_out_stream, const StreamType & in_stream) { -BaseObj * base_obj; -int method_index; -typename Functions::UserFunction * fun; -Item * item_block; -Var * variable; +FindHelper find_helper; std::vector parameters; -morm::Model * model; if( clear_out_stream ) ClearStream(out_stream); @@ -1278,12 +1393,8 @@ morm::Model * model; 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; - } + if( !Find(item_fun, *fun_name, find_helper) ) + return false; parameters.resize(item_fun.parameters.size()); @@ -1311,20 +1422,22 @@ morm::Model * model; } } - if( model ) - CallModel(*model, item_fun.fields, parameters, out_stream, in_stream); +#ifdef EZC_HAS_MORM_LIBRARY + if( find_helper.model_wrapper ) + CallModelWrapper(*find_helper.model_wrapper, item_fun.fields, parameters, out_stream, in_stream); else - if( base_obj ) - CallObject(base_obj, method_index, parameters, out_stream, in_stream); +#endif + if( find_helper.base_obj ) + CallObject(*find_helper.base_obj, find_helper.method_index, parameters, out_stream, in_stream); else - if( fun ) - CallFunction(fun, parameters, out_stream, in_stream); + if( find_helper.function ) + CallFunction(*find_helper.function, parameters, out_stream, in_stream); else - if( item_block ) - return CallBlock(*item_block, parameters, out_stream); + if( find_helper.item_block ) + return CallBlock(*find_helper.item_block, parameters, out_stream); else - if( variable ) - return CallVariable(item_fun, variable, parameters, out_stream, in_stream); + if( find_helper.variable ) + return CallVariable(item_fun, *find_helper.variable, parameters, out_stream, in_stream); return true; } diff --git a/src/models.cpp b/src/models.cpp index 1f084a9..151726e 100644 --- a/src/models.cpp +++ b/src/models.cpp @@ -38,22 +38,56 @@ #include "models.h" +#ifdef EZC_HAS_MORM_LIBRARY + + + namespace Ezc { + +Models::Models() +{ +} + + +Models::~Models() +{ + Clear(); +} + + +void Models::Clear() +{ + for(auto & map_item : models_map) + { + if( map_item.second->should_be_auto_removed() ) + { + delete map_item.second; + map_item.second = nullptr; + } + } + + models_map.clear(); +} + + + void Models::Add(const std::wstring & name, morm::Model & model) { - models_map[name] = &model; + morm::ModelWrapper * models_base = new morm::ModelWrapperModel(&model); + models_map[name] = models_base; } void Models::Add(const std::wstring & name, morm::Model * model) { - models_map[name] = model; + morm::ModelWrapper * models_base = new morm::ModelWrapperModel(model); + models_map[name] = models_base; } -morm::Model * Models::Find(const std::wstring & name) +morm::ModelWrapper * Models::Find(const std::wstring & name) { auto iterator = models_map.find(name); @@ -66,14 +100,9 @@ morm::Model * Models::Find(const std::wstring & name) } -void Models::Clear() -{ - models_map.clear(); -} - - - } +#endif + diff --git a/src/models.h b/src/models.h index a5dc030..2a76079 100644 --- a/src/models.h +++ b/src/models.h @@ -38,35 +38,69 @@ #ifndef headerfile_ezc_models #define headerfile_ezc_models -#include -#include +#ifdef EZC_HAS_MORM_LIBRARY -// put some macros -#include "model.h" +#include "modelwrapper.h" +#include "funinfo.h" namespace Ezc { + class Models { public: + Models(); + ~Models(); + 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); + template + void Add(const std::wstring & name, std::vector & container) + { + morm::ModelWrapper * models_base = new morm::ModelWrapperVector(&container); + models_map[name] = models_base; + } + + template + void Add(const std::wstring & name, std::vector * container) + { + morm::ModelWrapper * models_base = new morm::ModelWrapperVector(container); + models_map[name] = models_base; + } + + template + void Add(const std::wstring & name, std::list & container) + { + morm::ModelWrapper * models_base = new morm::ModelWrapperList(&container); + models_map[name] = models_base; + } + + template + void Add(const std::wstring & name, std::list * container) + { + morm::ModelWrapper * models_base = new morm::ModelWrapperList(container); + models_map[name] = models_base; + } + + + morm::ModelWrapper * Find(const std::wstring & name); void Clear(); + protected: + std::map models_map; - std::map models_map; }; } +#endif #endif From abb60def6e9cac800c0f8e53c3792a743a50a054 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Wed, 16 Jun 2021 14:21:08 +0200 Subject: [PATCH 03/19] added .editorconfig file --- .editorconfig | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..e34073d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,21 @@ +# EditorConfig +# https://editorconfig.org/ +# https://editorconfig-specification.readthedocs.io/ + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true + +# 4 space indentation +[*.{h,cpp,html,css,js,conf,txt}] +indent_style = tab +indent_size = 4 + +# Tab indentation (no size specified) +[Makefile] +indent_style = tab +indent_size = 4 From 4a643368644d65e679c55214e78f194651dffa86 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Thu, 17 Jun 2021 21:33:28 +0200 Subject: [PATCH 04/19] added support for morm containers with pointers to models --- src/models.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/models.h b/src/models.h index 2a76079..e492837 100644 --- a/src/models.h +++ b/src/models.h @@ -72,6 +72,20 @@ public: models_map[name] = models_base; } + template + void Add(const std::wstring & name, std::vector & container) + { + morm::ModelWrapper * models_base = new morm::ModelWrapperVectorPointer(&container); + models_map[name] = models_base; + } + + template + void Add(const std::wstring & name, std::vector * container) + { + morm::ModelWrapper * models_base = new morm::ModelWrapperVectorPointer(container); + models_map[name] = models_base; + } + template void Add(const std::wstring & name, std::list & container) { @@ -86,6 +100,19 @@ public: models_map[name] = models_base; } + template + void Add(const std::wstring & name, std::list & container) + { + morm::ModelWrapper * models_base = new morm::ModelWrapperListPointer(&container); + models_map[name] = models_base; + } + + template + void Add(const std::wstring & name, std::list * container) + { + morm::ModelWrapper * models_base = new morm::ModelWrapperListPointer(container); + models_map[name] = models_base; + } morm::ModelWrapper * Find(const std::wstring & name); void Clear(); From d76bb9349b9d1dd6ff18b7c6118abbac9b00edb7 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Fri, 18 Jun 2021 18:55:39 +0200 Subject: [PATCH 05/19] added typename keyword to Generator::CallModelHelper Generator::FindLastModelWrapper(...) --- src/generator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/generator.h b/src/generator.h index 4f61a05..cebc526 100644 --- a/src/generator.h +++ b/src/generator.h @@ -1198,7 +1198,7 @@ void Generator::CallModel(morm::Model & model, const std::wstring & template -Generator::CallModelHelper Generator::FindLastModelWrapper(morm::ModelWrapper & models_base, std::vector & fields) +typename Generator::CallModelHelper Generator::FindLastModelWrapper(morm::ModelWrapper & models_base, std::vector & fields) { CallModelHelper helper; helper.field_index = 0; From 9c4fe5179081c4589a0031f3187fee25783a34e5 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Sat, 19 Jun 2021 20:18:30 +0200 Subject: [PATCH 06/19] Generator uses now pt::Log as a logger - added method SetLogger(pt::Log & logger) - removed SetCommentary(...) methods - added logs when a model is not found PatternParser uses only pt::Log - removed SetCommentary(...) methods --- src/generator.h | 231 +++++++++++++++++++++--------------------- src/patternparser.cpp | 64 +++--------- src/patternparser.h | 11 -- 3 files changed, 126 insertions(+), 180 deletions(-) diff --git a/src/generator.h b/src/generator.h index cebc526..f77b1bb 100644 --- a/src/generator.h +++ b/src/generator.h @@ -49,6 +49,7 @@ #include "outstreams.h" #include "expressionparser.h" #include "models.h" +#include "log/log.h" #ifdef EZC_HAS_MORM_LIBRARY #include "model.h" @@ -79,6 +80,8 @@ public: void SetObjects(Objects & objects); void SetVariables(Vars & variables); // [def] and [let] + void SetLogger(pt::Log & logger); + #ifdef EZC_HAS_MORM_LIBRARY void SetModels(Models & models); #endif @@ -131,19 +134,13 @@ public: void Generate(OutStreams & out_streams); - void SetCommentary(const char * com_start, const char * com_stop); - void SetCommentary(const std::string & com_start, const std::string & com_stop); - void SetCommentary(const wchar_t * com_start, const wchar_t * com_stop); - void SetCommentary(const std::wstring & com_start, const std::wstring & com_stop); private: struct FindHelper { - #ifdef EZC_HAS_MORM_LIBRARY - morm::ModelWrapper * model_wrapper; - #endif + std::wstring * fun_name; BaseObj * base_obj; int method_index; @@ -151,17 +148,23 @@ private: Item * item_block; Var * variable; + #ifdef EZC_HAS_MORM_LIBRARY + morm::ModelWrapper * model_wrapper; + #endif FindHelper() { - #ifdef EZC_HAS_MORM_LIBRARY - model_wrapper = nullptr; - #endif + fun_name = nullptr; + base_obj = nullptr; method_index = -1; function = nullptr; item_block = nullptr; variable = nullptr; + + #ifdef EZC_HAS_MORM_LIBRARY + model_wrapper = nullptr; + #endif } }; @@ -208,7 +211,9 @@ private: #ifdef EZC_HAS_MORM_LIBRARY Models * pmodels; #endif - Vars * pvars; + Vars * pvars; + + pt::Log * plog; // pointer to the output streams map (can be null) // output stream will be created when [ezc frame "stream_name"] statement is found @@ -262,8 +267,6 @@ private: // a stack for [for] statements std::vector stack_tab; - std::wstring commentary_start, commentary_stop; - bool can_use_vars; bool can_find_in_cache; bool program_mode; @@ -298,16 +301,14 @@ private: bool FindInCache(Item::Function & item_fun, FindHelper & find_helper); #ifdef EZC_HAS_MORM_LIBRARY - bool FindInModels(const std::wstring & name, FindHelper & find_helper); + bool FindInModels(FindHelper & find_helper); #endif bool FindInFunctionsAndBlocks(const std::wstring & name, FindHelper & find_helper); bool FindInVariables(const std::wstring & name, FindHelper & find_helper); - bool Find(Item::Function & item_fun, - std::wstring & fun_name, - FindHelper & find_helper); + bool Find(Item::Function & item_fun, FindHelper & find_helper); void CallFunction(typename Functions::UserFunction & function, FunInfo & info); @@ -323,9 +324,9 @@ private: void CallObject(BaseObj & base_obj, int method_index, FunInfo & info); #ifdef EZC_HAS_MORM_LIBRARY - void CallModel(morm::Model & model, const std::wstring & field, std::vector parameters, StreamType & out_stream, const StreamType & in_stream); + bool CallModel(morm::Model & model, const std::wstring & field, std::vector parameters, StreamType & out_stream, const StreamType & in_stream); CallModelHelper FindLastModelWrapper(morm::ModelWrapper & models_base, std::vector & fields); - void CallModelWrapper(morm::ModelWrapper & models_base, std::vector & fields, std::vector parameters, StreamType & out_stream, const StreamType & in_stream); + void CallModelWrapper(FindHelper & find_helper, std::vector & fields, std::vector parameters, StreamType & out_stream, const StreamType & in_stream); #endif void CallObject(BaseObj & base_obj, @@ -361,12 +362,14 @@ private: void CopyTmpStreamToOutputStreams(Item::Function & fun, StreamType & ezc_out_tmp_stream, StreamType & previous_stream); - void CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t * arg = 0); - void CreateMsg(StreamType & stream, const wchar_t * type, const wchar_t * arg = 0); - void CreateMsg(const wchar_t * type, const wchar_t * arg = 0); + + void CreateMsg(const wchar_t * type, const std::wstring & model_name, std::vector & fields, + const wchar_t * arg = nullptr, const wchar_t * arg2 = nullptr, const wchar_t * arg3 = nullptr); + + void CreateMsg(const wchar_t * type, const wchar_t * arg = nullptr); void CreateMsg(const std::wstring & type, const std::wstring & arg); void CreateMsg(const std::wstring & type); - void CreateUnknownMsg(const std::wstring & fun); + bool LimitAchieved(); void EvaluateProgramNode(Item & item); @@ -408,6 +411,7 @@ Generator::Generator() : empty_stream() pfunctions = nullptr; pobjects = nullptr; pvars = nullptr; + plog = nullptr; #ifdef EZC_HAS_MORM_LIBRARY pmodels = nullptr; @@ -446,6 +450,7 @@ Generator & Generator::operator=(const Generator::~Generator() } -template -void Generator::SetCommentary(const char * com_start, const char * com_stop) -{ - pt::utf8_to_wide(com_start, commentary_start); - pt::utf8_to_wide(com_stop, commentary_stop); -} - - - -template -void Generator::SetCommentary(const std::string & com_start, const std::string & com_stop) -{ - pt::utf8_to_wide(com_start, commentary_start); - pt::utf8_to_wide(com_stop, commentary_stop); -} - - - -template -void Generator::SetCommentary(const wchar_t * com_start, const wchar_t * com_stop) -{ - commentary_start = com_start; - commentary_stop = com_stop; -} - - - -template -void Generator::SetCommentary(const std::wstring & com_start, const std::wstring & com_stop) -{ - commentary_start = com_start; - commentary_stop = com_stop; -} - - template void Generator::SetPattern(Pattern & pattern) @@ -567,6 +537,14 @@ void Generator::SetVariables(Vars & variables) } +template +void Generator::SetLogger(pt::Log & logger) +{ + plog = &logger; +} + + + #ifdef EZC_HAS_MORM_LIBRARY template void Generator::SetModels(Models & models) @@ -942,11 +920,11 @@ return false; #ifdef EZC_HAS_MORM_LIBRARY template -bool Generator::FindInModels(const std::wstring & name, FindHelper & find_helper) +bool Generator::FindInModels(FindHelper & find_helper) { if( pmodels ) { - morm::ModelWrapper * m = pmodels->Find(name); + morm::ModelWrapper * m = pmodels->Find(*find_helper.fun_name); if( m ) { @@ -1025,12 +1003,10 @@ bool Generator::FindInVariables(const std::wstring & name, FindHelpe * and if not null then means: as a funcion name we are not using item_fun.name but fun_name */ template -bool Generator::Find(Item::Function & item_fun, - std::wstring & fun_name, - FindHelper & find_helper) +bool Generator::Find(Item::Function & item_fun, FindHelper & find_helper) { #ifdef EZC_HAS_MORM_LIBRARY - if( FindInModels(fun_name, find_helper) ) + if( FindInModels(find_helper) ) return true; #endif @@ -1040,13 +1016,13 @@ bool Generator::Find(Item::Function & item_fun, if( FindInCache(item_fun, find_helper) ) return true; - if( FindInFunctionsAndBlocks(fun_name, find_helper) ) + if( FindInFunctionsAndBlocks(*find_helper.fun_name, find_helper) ) return true; - if( FindInVariables(fun_name, find_helper) ) + if( FindInVariables(*find_helper.fun_name, find_helper) ) return true; - CreateUnknownMsg(fun_name); + CreateMsg(L"unknown function", find_helper.fun_name->c_str()); return false; } @@ -1168,7 +1144,7 @@ bool Generator::ShouldEscapeValue(std::vector parameters) #ifdef EZC_HAS_MORM_LIBRARY template -void Generator::CallModel(morm::Model & model, const std::wstring & field, std::vector parameters, StreamType & out_stream, const StreamType & in_stream) +bool Generator::CallModel(morm::Model & model, const std::wstring & field, std::vector parameters, StreamType & out_stream, const StreamType & in_stream) { /* * if 'field' is a POD type then 'str' will be used in get_raw_value() @@ -1177,22 +1153,28 @@ void Generator::CallModel(morm::Model & model, const std::wstring & * */ pt::TextStream str; + bool found = false; if( parameters.empty() ) { FunInfo info(out_stream, parameters, empty, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item); - model.get_raw_value(nullptr, field.c_str(), nullptr, info, str, false); + found = model.get_raw_value(nullptr, field.c_str(), nullptr, info, str, false); last_res = info.res; } else { FunInfo info(out_stream, parameters, parameters[0].str, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item); - model.get_raw_value(nullptr, field.c_str(), nullptr, info, str, false); + found = model.get_raw_value(nullptr, field.c_str(), nullptr, info, str, false); last_res = info.res; } - bool should_escape = ShouldEscapeValue(parameters); - CopyStream(str, out_stream, should_escape); + if( found ) + { + bool should_escape = ShouldEscapeValue(parameters); + CopyStream(str, out_stream, should_escape); + } + + return found; } @@ -1238,11 +1220,11 @@ typename Generator::CallModelHelper Generator::FindLastM template -void Generator::CallModelWrapper(morm::ModelWrapper & models_base_root, std::vector & fields, +void Generator::CallModelWrapper(FindHelper & find_helper, std::vector & fields, std::vector parameters, StreamType & out_stream, const StreamType & in_stream) { last_res = false; - CallModelHelper helper = FindLastModelWrapper(models_base_root, fields); + CallModelHelper helper = FindLastModelWrapper(*find_helper.model_wrapper, fields); // if: // helper.field_index == fields.size() - all fields items are models or models containers @@ -1251,8 +1233,7 @@ void Generator::CallModelWrapper(morm::ModelWrapper & models_base_ro if( helper.field_index + 1 < fields.size() ) { - // put some log - // at the end there are some fields which are not models nor models containers + CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", ", fields[helper.field_index].c_str(), L" is not a model nor a model container"); last_res = false; return; } @@ -1263,13 +1244,15 @@ void Generator::CallModelWrapper(morm::ModelWrapper & models_base_ro if( helper.model ) { - CallModel(*helper.model, fields[helper.field_index], parameters, out_stream, in_stream); + if( !CallModel(*helper.model, fields[helper.field_index], parameters, out_stream, in_stream) ) + { + CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", unknown ", fields[helper.field_index].c_str()); + } } else { last_res = false; - // put log something like: - // model not set, have you forgotten to use [for ...] statement? + CreateMsg(L"model ", *find_helper.fun_name, fields, L" is not initialized, have you forgotten to use [for ...] statement?"); } } else @@ -1390,10 +1373,12 @@ std::vector parameters; if( clear_out_stream ) ClearStream(out_stream); - if( !fun_name ) - fun_name = &item_fun.name; + find_helper.fun_name = fun_name; - if( !Find(item_fun, *fun_name, find_helper) ) + if( !find_helper.fun_name ) + find_helper.fun_name = &item_fun.name; + + if( !Find(item_fun, find_helper) ) return false; parameters.resize(item_fun.parameters.size()); @@ -1424,7 +1409,7 @@ std::vector parameters; #ifdef EZC_HAS_MORM_LIBRARY if( find_helper.model_wrapper ) - CallModelWrapper(*find_helper.model_wrapper, item_fun.fields, parameters, out_stream, in_stream); + CallModelWrapper(find_helper, item_fun.fields, parameters, out_stream, in_stream); else #endif if( find_helper.base_obj ) @@ -1663,7 +1648,7 @@ void Generator::CopyTmpStreamToOutputStreams(Item::Function & fun, S } else { - CreateMsg(previous_stream, L"limit of output streams in OutStreams<> has been reached"); + CreateMsg(L"limit of output streams in OutStreams<> has been reached"); } } else @@ -1678,41 +1663,58 @@ void Generator::CopyTmpStreamToOutputStreams(Item::Function & fun, S -template -void Generator::CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t * arg) -{ - out = commentary_start; - out += L"Ezc runtime error: "; - out += type; - - if( arg ) - { - out += ' '; - out += arg; - } - - out += commentary_stop; -} - - -template -void Generator::CreateMsg(StreamType & stream, const wchar_t * type, const wchar_t * arg) -{ - CreateMsg(temp_msg, type, arg); - stream.write(temp_msg.c_str(), temp_msg.size()); - temp_msg.clear(); -} - template void Generator::CreateMsg(const wchar_t * type, const wchar_t * arg) { - if( output_stream ) - CreateMsg(*output_stream, type, arg); + if( plog ) + { + (*plog) << pt::Log::log2 << L"Ezc: runtime error: " << type; + + if( arg ) + { + (*plog) << arg; + } + + (*plog) << pt::Log::logend; + } } +template +void Generator::CreateMsg(const wchar_t * type, const std::wstring & model_name, std::vector & fields, + const wchar_t * arg, const wchar_t * arg2, const wchar_t * arg3) +{ + if( plog ) + { + (*plog) << pt::Log::log2 << L"Ezc: " << type << model_name; + + for(std::wstring & str : fields) + { + (*plog) << '.' << str; + } + + if( arg ) + { + (*plog) << arg; + } + + if( arg2 ) + { + (*plog) << arg2; + } + + if( arg3 ) + { + (*plog) << arg3; + } + + (*plog) << pt::Log::logend; + } +} + + template void Generator::CreateMsg(const std::wstring & type, const std::wstring & arg) { @@ -1728,13 +1730,6 @@ void Generator::CreateMsg(const std::wstring & type) } -template -void Generator::CreateUnknownMsg(const std::wstring & fun) -{ - CreateMsg(L"unknown function", fun.c_str()); -} - - template void Generator::EvaluateProgramNode(Item & item) diff --git a/src/patternparser.cpp b/src/patternparser.cpp index aed1e2d..d82b623 100644 --- a/src/patternparser.cpp +++ b/src/patternparser.cpp @@ -124,37 +124,6 @@ void PatternParser::SetBlocks(Blocks & blocks) } -void PatternParser::SetCommentary(const char * com_start, const char * com_stop) -{ - pt::utf8_to_wide(com_start, commentary_start); - pt::utf8_to_wide(com_stop, commentary_stop); -} - - - -void PatternParser::SetCommentary(const std::string & com_start, const std::string & com_stop) -{ - pt::utf8_to_wide(com_start, commentary_start); - pt::utf8_to_wide(com_stop, commentary_stop); -} - - - -void PatternParser::SetCommentary(const wchar_t * com_start, const wchar_t * com_stop) -{ - commentary_start = com_start; - commentary_stop = com_stop; -} - - - -void PatternParser::SetCommentary(const std::wstring & com_start, const std::wstring & com_stop) -{ - commentary_start = com_start; - commentary_stop = com_stop; -} - - void PatternParser::SetProgramMode(bool program_mode) { this->program_mode = program_mode; @@ -167,23 +136,6 @@ void PatternParser::SetLogger(pt::Log * log) } -void PatternParser::CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t * arg) -{ - out = commentary_start; - out += L"Ezc: "; - out += type; - - if( arg ) - { - out += ' '; - out += arg; - } - - out += commentary_stop; -} - - - void PatternParser::ParseFile(const std::string & file_name, Pattern & pattern) { ParseFile(file_name.c_str(), pattern); @@ -350,15 +302,25 @@ void PatternParser::ReadFile(const wchar_t * name, std::wstring & result) { if( !IsFileCorrect(name) ) { - CreateMsg(result, L"incorrect file name: ", name); + if( log ) + { + (*log) << pt::Log::log2 << "Ezc: incorrect file name: " << name << pt::Log::logend; + } } else { result.clear(); if( !ReadFileFromDir(directory, name, result) ) + { if( !ReadFileFromDir(directory2, name, result) ) - CreateMsg(result, L"can't open: ", name); + { + if( log ) + { + (*log) << pt::Log::log2 << "Ezc: can't open file: " << name << pt::Log::logend; + } + } + } } } @@ -1161,7 +1123,7 @@ void PatternParser::CreateTreeReadIncludeSkipAllowFlag(Item & item) { if( log ) { - (*log) << pt::Log::log1 << "Ezc: \"include\" directive has reached the maximum level" << pt::Log::logend; + (*log) << pt::Log::log2 << "Ezc: \"include\" directive has reached the maximum level" << pt::Log::logend; } return; diff --git a/src/patternparser.h b/src/patternparser.h index f2906e8..bab52f3 100644 --- a/src/patternparser.h +++ b/src/patternparser.h @@ -79,16 +79,8 @@ public: void AllowInclude(bool allow); void DeleteWhiteTextItems(bool del); void SetIncludeMax(int include_max); - void SetBlocks(Blocks & blocks); - - void SetCommentary(const char * com_start, const char * com_stop); - void SetCommentary(const std::string & com_start, const std::string & com_stop); - void SetCommentary(const wchar_t * com_start, const wchar_t * com_stop); - void SetCommentary(const std::wstring & com_start, const std::wstring & com_stop); - void SetProgramMode(bool program_mode); - void SetLogger(pt::Log * log); private: @@ -117,8 +109,6 @@ private: std::wstring directory, directory2; - std::wstring commentary_start, commentary_stop; - int include_level, include_level_max; @@ -140,7 +130,6 @@ private: pt::Log * log; - void CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t * arg = 0); void ReadFile(const std::wstring & name, std::wstring & result); void ReadFile(const wchar_t * name, std::wstring & result); From 615bad7372d5a7bb4da40a7dd815cc9702f731e3 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Sun, 20 Jun 2021 16:54:55 +0200 Subject: [PATCH 07/19] renamed macro: EZC_HAS_SPECIAL_STREAM -> EZC_GENERATOR_HAS_PT_STREAM added macro EZC_GENERATOR_HAS_WINIX_STREAM which is used by Generator::CopyStream(pt::WTextStream & src_stream, StreamType & dst_stream, bool should_escape) if this macro is defined then Generator is able to escape output stream --- src/generator.h | 206 ++++++++++++++++++++++++++++------------------- src/outstreams.h | 4 +- 2 files changed, 124 insertions(+), 86 deletions(-) diff --git a/src/generator.h b/src/generator.h index f77b1bb..f49f90c 100644 --- a/src/generator.h +++ b/src/generator.h @@ -50,6 +50,9 @@ #include "expressionparser.h" #include "models.h" #include "log/log.h" +#include "utf8/utf8.h" + + #ifdef EZC_HAS_MORM_LIBRARY #include "model.h" @@ -288,6 +291,11 @@ private: void ClearEzcFrameTab(); void ClearStream(StreamType & str); + void CopyStreamToString(StreamType & src_stream, std::wstring & dst_string); + void CopyStream(StreamType & src_stream, StreamType & dst_stream); + void CopyStream(pt::WTextStream & src_stream, StreamType & dst_stream, bool should_escape); + + void RemoveStackFunData(Stack & sitem); bool ConvertToBool(const std::wstring & str); @@ -357,7 +365,6 @@ 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); @@ -379,7 +386,7 @@ private: void MakeTextFor(Item & item); void MakeItemText(Item & item); void MakeTextContainer(Item & item); - void MakeTextNormal(Item & item); + void MakeTextFunction(Item & item); void MakeTextDefine(Item & item, Var & var); void MakeTextDefine(Item & item); void MakeTextDefineIfNotSet(Item & item); @@ -708,14 +715,91 @@ void Generator::ClearForStack() template void Generator::ClearStream(StreamType & str) { - #ifdef EZC_HAS_SPECIAL_STREAM - str.Clear(); + #ifdef EZC_GENERATOR_HAS_PT_STREAM + str.clear(); #else str.str(L""); #endif } + +template +void Generator::CopyStreamToString(StreamType & src_stream, std::wstring & dst_string) +{ + if constexpr (sizeof(wchar_t) == sizeof(typename StreamType::char_type)) + { + #ifdef EZC_GENERATOR_HAS_PT_STREAM + src_stream.to_str(dst_string); + #else + dst_string = src_stream.str(); + #endif + } + else + { + #ifdef EZC_GENERATOR_HAS_PT_STREAM + src_stream.to_str(dst_string); + #else + std::string tmp = src_stream.str(); + pt::utf8_to_wide(tmp, dst_string); + #endif + } +} + + +template +void Generator::CopyStream(StreamType & src_stream, StreamType & dst_stream) +{ + #ifdef EZC_GENERATOR_HAS_PT_STREAM + dst_stream << src_stream; + #else + dst_stream << src_stream.str(); + #endif +} + + +template +void Generator::CopyStream(pt::WTextStream & src_stream, StreamType & dst_stream, bool should_escape) +{ + if constexpr(sizeof(char) == sizeof(typename StreamType::char_type)) + { + // winix html stream is always wide (wchar_t) + // so if we are here then the dst_stream cannot be a Winix::HtmlTextStream + #ifndef EZC_GENERATOR_HAS_WINIX_STREAM + + wide_stream_to_utf8(src_stream, dst_stream, false); + + #endif + } + else + { + pt::WTextStream::iterator i = src_stream.begin(); + + while( i != src_stream.end() ) + { + #ifdef EZC_GENERATOR_HAS_WINIX_STREAM + + // IMPROVEME we need a better api from winix htmltextstream + + if( should_escape ) + { + dst_stream << *i; + } + else + { + dst_stream.write(&(*i), 1); + } + #else + dst_stream.write(&(*i), 1); + #endif + + ++i; + } + } +} + + + template void Generator::RemoveStackFunData(Stack & s) { @@ -1008,6 +1092,13 @@ bool Generator::Find(Item::Function & item_fun, FindHelper & find_he #ifdef EZC_HAS_MORM_LIBRARY if( FindInModels(find_helper) ) return true; + + if( !item_fun.fields.empty() ) + { + CreateMsg(L"unknown model", find_helper.fun_name->c_str()); + return false; + } + #endif if( CheckBlockArgument(item_fun.arg, find_helper) ) @@ -1092,34 +1183,6 @@ 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 - { - if constexpr(sizeof(pt::TextStream::char_type) == sizeof(typename StreamType::char_type)) - { - dst_stream.write(&(*i), 1); - } - else - { - wchar_t buf = static_cast(*i); - dst_stream.write(&buf, 1); - } - } - - ++i; - } -} - template @@ -1148,11 +1211,11 @@ bool Generator::CallModel(morm::Model & model, const std::wstring & { /* * if 'field' is a POD type then 'str' will be used in get_raw_value() - * if 'field' is a getter method with pt::TextStream then 'str' will be used too + * if 'field' is a getter method with pt::Stream then 'str' will be used too * if 'field' is a getter method which takes FunInfo<> then out_stream will be used and 'str' will be empty * */ - pt::TextStream str; + pt::WTextStream str; bool found = false; if( parameters.empty() ) @@ -1168,7 +1231,7 @@ bool Generator::CallModel(morm::Model & model, const std::wstring & last_res = info.res; } - if( found ) + if( found && !str.empty()) { bool should_escape = ShouldEscapeValue(parameters); CopyStream(str, out_stream, should_escape); @@ -1320,13 +1383,7 @@ bool Generator::CallBlock(Item & item_block, MakeText(item_block); - #ifdef EZC_HAS_SPECIAL_STREAM - const std::wstring & str = output_stream->Str(); - #else - const std::wstring & str = output_stream->str(); - #endif - - out_stream.write(str.c_str(), str.size()); + CopyStream(*output_stream, out_stream); // last_res is set by [return ...] statement or other last evaluated function ClearStream(*output_stream); @@ -1392,12 +1449,7 @@ std::vector parameters; StreamType local_temp_stream; Call(fun_child, nullptr, local_temp_stream, true, empty_stream); - #ifdef EZC_HAS_SPECIAL_STREAM - parameters[i].str = local_temp_stream.Str(); - #else - parameters[i].str = local_temp_stream.str(); - #endif - + CopyStreamToString(local_temp_stream, parameters[i].str); parameters[i].res = last_res; } else @@ -1621,42 +1673,33 @@ void Generator::CopyTmpStreamToOutputStreams(Item::Function & fun, S { if( output_frames_streams ) { - #ifdef EZC_HAS_SPECIAL_STREAM - const std::wstring & str = ezc_out_tmp_stream.Str(); - #else - const std::wstring & str = ezc_out_tmp_stream.str(); - #endif + CopyStream(ezc_out_tmp_stream, previous_stream); - if( !str.empty() ) + for(size_t s=0 ; s < fun.parameters.size() ; ++s) { - previous_stream.write(str.c_str(), str.size()); + std::wstring & name = fun.parameters[s]->name; + auto imap = output_frames_streams->streams_map.find(name); - for(size_t s=0 ; s < fun.parameters.size() ; ++s) + if( imap == output_frames_streams->streams_map.end() ) { - std::wstring & name = fun.parameters[s]->name; - auto imap = output_frames_streams->streams_map.find(name); - - if( imap == output_frames_streams->streams_map.end() ) + if( output_frames_streams->streams_map.size() < output_frames_streams->streams_tab.size() ) { - if( output_frames_streams->streams_map.size() < output_frames_streams->streams_tab.size() ) - { - /* a new stream from the pool (output_stream_tab) is taken */ - StreamType * stream = output_frames_streams->streams_tab[ output_frames_streams->streams_map.size() ]; - output_frames_streams->streams_map.insert(std::make_pair(name, stream)); - ClearStream(*stream); - stream->write(str.c_str(), str.size()); - } - else - { - CreateMsg(L"limit of output streams in OutStreams<> has been reached"); - } + /* a new stream from the pool (output_stream_tab) is taken */ + StreamType * stream = output_frames_streams->streams_tab[ output_frames_streams->streams_map.size() ]; + output_frames_streams->streams_map.insert(std::make_pair(name, stream)); + ClearStream(*stream); + CopyStream(ezc_out_tmp_stream, *stream); } else { - StreamType * stream = imap->second; - stream->write(str.c_str(), str.size()); + CreateMsg(L"limit of output streams in OutStreams<> has been reached"); } } + else + { + StreamType * stream = imap->second; + CopyStream(ezc_out_tmp_stream, *stream); + } } } } @@ -1669,11 +1712,11 @@ void Generator::CreateMsg(const wchar_t * type, const wchar_t * arg) { if( plog ) { - (*plog) << pt::Log::log2 << L"Ezc: runtime error: " << type; + (*plog) << pt::Log::log2 << "Ezc: " << type; if( arg ) { - (*plog) << arg; + (*plog) << ' ' << arg; } (*plog) << pt::Log::logend; @@ -1804,7 +1847,7 @@ void Generator::MakeTextContainer(Item & item) template -void Generator::MakeTextNormal(Item & item) +void Generator::MakeTextFunction(Item & item) { is_generating_normal = true; @@ -1928,12 +1971,7 @@ void Generator::MakeTextDefine(Item & item, Var & var) // call function if( Call(fun, nullptr, stream_temp_define, true, empty_stream) ) { - #ifdef EZC_HAS_SPECIAL_STREAM - var.str += stream_temp_define.Str(); - #else - var.str += stream_temp_define.str(); - #endif - + CopyStreamToString(stream_temp_define, var.str); var.res = last_res; } else @@ -2222,7 +2260,7 @@ void Generator::MakeText(Item & item) if ( item.type == Item::item_text ) MakeItemText(item); else if( item.type == Item::item_container ) MakeTextContainer(item); - else if( item.type == Item::item_function ) MakeTextNormal(item); + else if( item.type == Item::item_function ) MakeTextFunction(item); else if( item.type == Item::item_if ) MakeTextIf(item); else if( item.type == Item::item_def ) MakeTextDefine(item); else if( item.type == Item::item_def_if_not_set ) MakeTextDefineIfNotSet(item); diff --git a/src/outstreams.h b/src/outstreams.h index 5727044..df5840b 100644 --- a/src/outstreams.h +++ b/src/outstreams.h @@ -150,8 +150,8 @@ void OutStreams::ClearMap() { StreamType & str = *(i->second); - #ifdef EZC_HAS_SPECIAL_STREAM - str.Clear(); + #ifdef EZC_GENERATOR_HAS_PT_STREAM + str.clear(); #else str.str(L""); #endif From e442ee4720847bf63d04ce2e8da6b3d18734f929 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Sun, 20 Jun 2021 16:55:39 +0200 Subject: [PATCH 08/19] make depend --- src/Makefile.dep | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile.dep b/src/Makefile.dep index 328b1be..f820e12 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -19,6 +19,7 @@ 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/textstream/textstream.h +patternparser.o: ../../pikotools/src/textstream/stream.h patternparser.o: ../../pikotools/src/space/space.h patternparser.o: ../../pikotools/src/textstream/types.h patternparser.o: ../../pikotools/src/convert/inttostr.h From eda276356fc85b03f306ab82fd3f70e88f3da5b1 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Tue, 22 Jun 2021 18:01:47 +0200 Subject: [PATCH 09/19] added possibility to iterate through Space object in Models objects --- src/generator.h | 210 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 194 insertions(+), 16 deletions(-) diff --git a/src/generator.h b/src/generator.h index f49f90c..276f5de 100644 --- a/src/generator.h +++ b/src/generator.h @@ -331,6 +331,9 @@ private: void CallObject(BaseObj & base_obj, int method_index, FunInfo & info); + void CallSpace(morm::ModelWrapper & model_wrapper, pt::Space & root_space, FindHelper & find_helper, std::vector & fields, size_t field_index, + std::vector & parameters, StreamType & out_stream); + #ifdef EZC_HAS_MORM_LIBRARY bool CallModel(morm::Model & model, const std::wstring & field, std::vector parameters, StreamType & out_stream, const StreamType & in_stream); CallModelHelper FindLastModelWrapper(morm::ModelWrapper & models_base, std::vector & fields); @@ -365,7 +368,10 @@ 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); - bool ShouldEscapeValue(std::vector parameters); + bool ShouldEscapeValue(std::vector & parameters); + bool ShouldMakeDump(std::vector & parameters); + bool IsCurrentParam(std::vector & parameters); + void CopyTmpStreamToOutputStreams(Item::Function & fun, StreamType & ezc_out_tmp_stream, StreamType & previous_stream); @@ -1186,7 +1192,7 @@ void Generator::CallObject(BaseObj & base_obj, int metho template -bool Generator::ShouldEscapeValue(std::vector parameters) +bool Generator::ShouldEscapeValue(std::vector & parameters) { for(Var & var : parameters) { @@ -1203,6 +1209,164 @@ bool Generator::ShouldEscapeValue(std::vector parameters) } +template +bool Generator::ShouldMakeDump(std::vector & parameters) +{ + for(Var & var : parameters) + { + if( !var.is_function ) + { + if( var.str == L"dump" || var.str == L"to_str" ) + { + return true; + } + } + } + + return false; +} + + +template +bool Generator::IsCurrentParam(std::vector & parameters) +{ + for(Var & var : parameters) + { + if( !var.is_function ) + { + if( var.str == L"current" ) + { + return true; + } + } + } + + return false; +} + + +template +void Generator::CallSpace(morm::ModelWrapper & model_wrapper, pt::Space & root_space, FindHelper & find_helper, std::vector & fields, size_t field_index, + std::vector & parameters, StreamType & out_stream) +{ + pt::Space * space = &root_space; + last_res = false; + std::wstring * field = nullptr; + + for(size_t i=field_index ; i < fields.size() + 1 ; ++i) + { + bool is_last_field = (i == fields.size()); + + if( i == 0 ) + field = find_helper.fun_name; + else + field = &fields[i - 1]; + + + if( space->is_object() ) + { + if( is_last_field ) + { + if( ShouldMakeDump(parameters) ) + { + space->serialize_to_json_stream(out_stream); // we can add pretty print + } + } + else + { + std::wstring & next_field = fields[i]; + space = space->get_object_field(next_field); + + if( !space ) + { + if( plog ) + { + (*plog) << pt::Log::log2 << "Ezc: there is no " << next_field << " property of object " << *field << pt::Log::logend; + } + + break; + } + } + } + else + if( space->is_table() ) + { + pt::Space::TableType * table = space->get_table(); + size_t space_index = i - field_index; + + // add testing space_index range [0..MODEL_WRAPPER_SPACE_INDICES_TABLE_SIZE - 1] + + if( is_last_field ) + { + if( stack_tab[stack_index-1].is_for ) + { + // we are in [for...]statement, increment iterator and check the range + model_wrapper.increment_iterator(space_index, table->size()); + size_t iterator_value = model_wrapper.get_space_iterator_value(space_index); + last_res = (iterator_value < table->size()); + } + else + { + // we are not in [for..], it can be for example [if...], return true if the table is not empty + last_res = !table->empty(); + } + + if( ShouldMakeDump(parameters) ) + { + space->serialize_to_json_stream(out_stream); + } + + if( IsCurrentParam(parameters) ) + { + size_t iterator_value = model_wrapper.get_space_iterator_value(space_index); + + if( iterator_value < table->size() ) + { + (*table)[iterator_value]->serialize_to_json_stream(out_stream); + } + } + } + else + { + // check the current iterator, if it is correct then select the item from the table + size_t iterator_value = model_wrapper.get_space_iterator_value(space_index); + last_res = (iterator_value < table->size()); + + if( last_res ) + { + space = (*table)[iterator_value]; + } + else + { + // IMPROVEME use CreateMsg() + if( plog ) + { + (*plog) << pt::Log::log1 << "Ezc: table: " << field << " is not initialized, have you forgotten to use [for...] statement?" << pt::Log::logend; + } + break; + } + } + } + else + { + if( is_last_field ) + { + space->serialize_to_string(out_stream); + } + else + { + if( plog ) + { + (*plog) << pt::Log::log2 << "Ezc: " << (*field) << " is not a model not a model container nor a space" << pt::Log::logend; + } + + break; + } + } + } +} + + #ifdef EZC_HAS_MORM_LIBRARY @@ -1250,31 +1414,31 @@ typename Generator::CallModelHelper Generator::FindLastM helper.model_wrapper = &models_base; helper.model = nullptr; - for(; helper.field_index < fields.size() ; ++helper.field_index) + for(; helper.field_index < fields.size() && !helper.model_wrapper->get_space() ; ++helper.field_index) { std::wstring & field = fields[helper.field_index]; - morm::ModelWrapper * child_models_base = helper.model_wrapper->find_child(field); + morm::ModelWrapper * child_model_wrapper = helper.model_wrapper->find_child(field); - if( !child_models_base ) + if( !child_model_wrapper ) { helper.model = helper.model_wrapper->get_model(); // this can return null for lists/vectors in a case when the iterator is not pointing to a valid item if( helper.model ) { - child_models_base = helper.model->get_model_wrapper(nullptr, field.c_str(), false); + child_model_wrapper = helper.model->get_model_wrapper(nullptr, field.c_str(), false); - if( child_models_base ) + if( child_model_wrapper ) { - helper.model_wrapper->add_child(field, child_models_base); + helper.model_wrapper->add_child(field, child_model_wrapper); } } } - if( !child_models_base ) + if( !child_model_wrapper ) break; - helper.model_wrapper = child_models_base; + helper.model_wrapper = child_model_wrapper; helper.model = nullptr; } @@ -1294,13 +1458,22 @@ void Generator::CallModelWrapper(FindHelper & find_helper, std::vect // helper.field_index == fields.size()-1 - last field is not a model nor a models container // helper.field_index < fields.size()-1 - incorrect + //morm::Model * model = helper.model_wrapper->get_model(); + pt::Space * space = helper.model_wrapper->get_space(); + if( helper.field_index + 1 < fields.size() ) { - CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", ", fields[helper.field_index].c_str(), L" is not a model nor a model container"); - last_res = false; - return; + if( space ) + { + CallSpace(*helper.model_wrapper, *space, find_helper, fields, helper.field_index, parameters, out_stream); + } + else + { + CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", ", fields[helper.field_index].c_str(), L" is not a model nor a model container nor a space"); + last_res = false; + } } - + else if( helper.field_index + 1 == fields.size() ) { // last field is not a model nor a models container @@ -1313,18 +1486,23 @@ void Generator::CallModelWrapper(FindHelper & find_helper, std::vect } } else + if( space ) + { + CallSpace(*helper.model_wrapper, *space, find_helper, fields, helper.field_index, parameters, out_stream); + } + else { last_res = false; - CreateMsg(L"model ", *find_helper.fun_name, fields, L" is not initialized, have you forgotten to use [for ...] statement?"); + CreateMsg(L"model ", *find_helper.fun_name, fields, L" is not initialized, have you forgotten to use [for ...] statement?"); // a different msg if we are using Space? } } else { // all fields items are models or models containers // this is usualy in [for...] or [if ...] statements - // helper.model_wrapper is always set if( stack_tab[stack_index-1].is_for ) { + // helper.model_wrapper is always set helper.model_wrapper->increment_iterator(); helper.model_wrapper->clear_childs(); last_res = helper.model_wrapper->is_iterator_correct(); From 526d57b72e1410db78041efba76e5adc7c414af3 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Wed, 23 Jun 2021 06:53:43 +0200 Subject: [PATCH 10/19] added possibility to take a Space struct in Models: Models::Add(const std::wstring & name, pt::Space & space); --- src/generator.h | 31 ++++++++++++++++++------------- src/models.cpp | 23 +++++++++++++++++++---- src/models.h | 36 ++++++++++++++++++++---------------- 3 files changed, 57 insertions(+), 33 deletions(-) diff --git a/src/generator.h b/src/generator.h index 276f5de..bad4940 100644 --- a/src/generator.h +++ b/src/generator.h @@ -1256,12 +1256,7 @@ void Generator::CallSpace(morm::ModelWrapper & model_wrapper, pt::Sp for(size_t i=field_index ; i < fields.size() + 1 ; ++i) { bool is_last_field = (i == fields.size()); - - if( i == 0 ) - field = find_helper.fun_name; - else - field = &fields[i - 1]; - + field = (i == 0) ? find_helper.fun_name : &fields[i - 1]; if( space->is_object() ) { @@ -1498,18 +1493,28 @@ void Generator::CallModelWrapper(FindHelper & find_helper, std::vect } else { - // all fields items are models or models containers + // all fields items are models or models containers or last one is Space // this is usualy in [for...] or [if ...] statements - if( stack_tab[stack_index-1].is_for ) + + if( space ) { - // helper.model_wrapper is always set - helper.model_wrapper->increment_iterator(); - helper.model_wrapper->clear_childs(); - last_res = helper.model_wrapper->is_iterator_correct(); + CallSpace(*helper.model_wrapper, *space, find_helper, fields, helper.field_index, parameters, out_stream); } else { - last_res = !helper.model_wrapper->is_container_empty(); + if( stack_tab[stack_index-1].is_for ) + { + // helper.model_wrapper is always set + helper.model_wrapper->increment_iterator(); + helper.model_wrapper->clear_childs(); + last_res = helper.model_wrapper->is_iterator_correct(); + } + else + { + last_res = !helper.model_wrapper->is_container_empty(); + } + + // add support for "dump" parameter } } } diff --git a/src/models.cpp b/src/models.cpp index 151726e..a2fb8b4 100644 --- a/src/models.cpp +++ b/src/models.cpp @@ -75,18 +75,33 @@ void Models::Clear() void Models::Add(const std::wstring & name, morm::Model & model) { - morm::ModelWrapper * models_base = new morm::ModelWrapperModel(&model); - models_map[name] = models_base; + morm::ModelWrapper * model_wrapper = new morm::ModelWrapperModel(&model); + models_map[name] = model_wrapper; } void Models::Add(const std::wstring & name, morm::Model * model) { - morm::ModelWrapper * models_base = new morm::ModelWrapperModel(model); - models_map[name] = models_base; + morm::ModelWrapper * model_wrapper = new morm::ModelWrapperModel(model); + models_map[name] = model_wrapper; } +void Models::Add(const std::wstring & name, pt::Space & space) +{ + morm::ModelWrapper * model_wrapper = new morm::ModelWrapperSpace(&space); + models_map[name] = model_wrapper; +} + + +void Models::Add(const std::wstring & name, pt::Space * space) +{ + morm::ModelWrapper * model_wrapper = new morm::ModelWrapperSpace(space); + models_map[name] = model_wrapper; +} + + + morm::ModelWrapper * Models::Find(const std::wstring & name) { auto iterator = models_map.find(name); diff --git a/src/models.h b/src/models.h index e492837..61204d9 100644 --- a/src/models.h +++ b/src/models.h @@ -42,6 +42,7 @@ #include "modelwrapper.h" #include "funinfo.h" +#include "space/space.h" namespace Ezc @@ -58,60 +59,63 @@ public: void Add(const std::wstring & name, morm::Model & model); void Add(const std::wstring & name, morm::Model * model); + void Add(const std::wstring & name, pt::Space & space); + void Add(const std::wstring & name, pt::Space * space); + template void Add(const std::wstring & name, std::vector & container) { - morm::ModelWrapper * models_base = new morm::ModelWrapperVector(&container); - models_map[name] = models_base; + morm::ModelWrapper * model_wrapper = new morm::ModelWrapperVector(&container); + models_map[name] = model_wrapper; } template void Add(const std::wstring & name, std::vector * container) { - morm::ModelWrapper * models_base = new morm::ModelWrapperVector(container); - models_map[name] = models_base; + morm::ModelWrapper * model_wrapper = new morm::ModelWrapperVector(container); + models_map[name] = model_wrapper; } template void Add(const std::wstring & name, std::vector & container) { - morm::ModelWrapper * models_base = new morm::ModelWrapperVectorPointer(&container); - models_map[name] = models_base; + morm::ModelWrapper * model_wrapper = new morm::ModelWrapperVectorPointer(&container); + models_map[name] = model_wrapper; } template void Add(const std::wstring & name, std::vector * container) { - morm::ModelWrapper * models_base = new morm::ModelWrapperVectorPointer(container); - models_map[name] = models_base; + morm::ModelWrapper * model_wrapper = new morm::ModelWrapperVectorPointer(container); + models_map[name] = model_wrapper; } template void Add(const std::wstring & name, std::list & container) { - morm::ModelWrapper * models_base = new morm::ModelWrapperList(&container); - models_map[name] = models_base; + morm::ModelWrapper * model_wrapper = new morm::ModelWrapperList(&container); + models_map[name] = model_wrapper; } template void Add(const std::wstring & name, std::list * container) { - morm::ModelWrapper * models_base = new morm::ModelWrapperList(container); - models_map[name] = models_base; + morm::ModelWrapper * model_wrapper = new morm::ModelWrapperList(container); + models_map[name] = model_wrapper; } template void Add(const std::wstring & name, std::list & container) { - morm::ModelWrapper * models_base = new morm::ModelWrapperListPointer(&container); - models_map[name] = models_base; + morm::ModelWrapper * model_wrapper = new morm::ModelWrapperListPointer(&container); + models_map[name] = model_wrapper; } template void Add(const std::wstring & name, std::list * container) { - morm::ModelWrapper * models_base = new morm::ModelWrapperListPointer(container); - models_map[name] = models_base; + morm::ModelWrapper * model_wrapper = new morm::ModelWrapperListPointer(container); + models_map[name] = model_wrapper; } morm::ModelWrapper * Find(const std::wstring & name); From 87ee461dd1c480e94fec467c5693c3d3f924deef Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Wed, 23 Jun 2021 17:02:19 +0200 Subject: [PATCH 11/19] make depend --- src/Makefile.dep | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile.dep b/src/Makefile.dep index f820e12..0440db1 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -33,3 +33,4 @@ 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 +patternparser.o: ../../pikotools/src/convert/double.h From 16bce07c75e8b123f33ec5ef111611dda88d3333 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Wed, 23 Jun 2021 21:56:04 +0200 Subject: [PATCH 12/19] fixed: in Space::CallSpace() we should not increment field index when a new table item is prepared --- src/generator.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/generator.h b/src/generator.h index bad4940..cee9647 100644 --- a/src/generator.h +++ b/src/generator.h @@ -1253,7 +1253,7 @@ void Generator::CallSpace(morm::ModelWrapper & model_wrapper, pt::Sp last_res = false; std::wstring * field = nullptr; - for(size_t i=field_index ; i < fields.size() + 1 ; ++i) + for(size_t i=field_index ; i < fields.size() + 1 ; ) { bool is_last_field = (i == fields.size()); field = (i == 0) ? find_helper.fun_name : &fields[i - 1]; @@ -1269,6 +1269,7 @@ void Generator::CallSpace(morm::ModelWrapper & model_wrapper, pt::Sp } else { + pt::Space * old = space; std::wstring & next_field = fields[i]; space = space->get_object_field(next_field); @@ -1282,6 +1283,8 @@ void Generator::CallSpace(morm::ModelWrapper & model_wrapper, pt::Sp break; } } + + ++i; } else if( space->is_table() ) @@ -1320,6 +1323,8 @@ void Generator::CallSpace(morm::ModelWrapper & model_wrapper, pt::Sp (*table)[iterator_value]->serialize_to_json_stream(out_stream); } } + + ++i; } else { @@ -1347,6 +1352,7 @@ void Generator::CallSpace(morm::ModelWrapper & model_wrapper, pt::Sp if( is_last_field ) { space->serialize_to_string(out_stream); + ++i; } else { From 5bd8eef3f255fbe7983913df2e66975363cd8f6a Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Thu, 24 Jun 2021 20:53:26 +0200 Subject: [PATCH 13/19] make depend --- src/Makefile.dep | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Makefile.dep b/src/Makefile.dep index 0440db1..b6e23c4 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -1,20 +1,24 @@ # DO NOT DELETE blocks.o: blocks.h item.h cache.h functions.h ../../pikotools/src/utf8/utf8.h +blocks.o: ../../pikotools/src/textstream/stream.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/stream.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 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/stream.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: ../../pikotools/src/utf8/utf8.h +patternparser.o: ../../pikotools/src/textstream/stream.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 From 3926793a17da3b94a55360ef8bbcc923f2f88e1d Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Fri, 25 Jun 2021 16:16:30 +0200 Subject: [PATCH 14/19] fixed in Generator::CallSpace() when a middle field was a table: last_res should be set only for last field refactoring in Generator::CallSpace() --- src/generator.h | 224 +++++++++++++++++++++++++++++++----------------- 1 file changed, 143 insertions(+), 81 deletions(-) diff --git a/src/generator.h b/src/generator.h index cee9647..93a98a3 100644 --- a/src/generator.h +++ b/src/generator.h @@ -331,8 +331,18 @@ private: void CallObject(BaseObj & base_obj, int method_index, FunInfo & info); - void CallSpace(morm::ModelWrapper & model_wrapper, pt::Space & root_space, FindHelper & find_helper, std::vector & fields, size_t field_index, - std::vector & parameters, StreamType & out_stream); + void CallSpaceObjectForLastField(std::vector & parameters, StreamType & out_stream, pt::Space * space); + + pt::Space * CallSpaceObjectForMiddleField(std::wstring & root_space_name, std::vector & fields, size_t field_index, pt::Space * space); + + void CallSpaceTableForLastField(morm::ModelWrapper & model_wrapper, std::vector & parameters, StreamType & out_stream, + pt::Space * space, size_t model_wrapper_space_table_index); + + pt::Space * CallSpaceTableForMiddleField(morm::ModelWrapper & model_wrapper, std::wstring & root_space_name, std::vector & fields, + size_t field_index, pt::Space * space, size_t model_wrapper_space_table_index); + + void CallSpace(morm::ModelWrapper & model_wrapper, pt::Space & root_space, FindHelper & find_helper, std::vector & fields, + size_t root_field_index, std::vector & parameters, StreamType & out_stream); #ifdef EZC_HAS_MORM_LIBRARY bool CallModel(morm::Model & model, const std::wstring & field, std::vector parameters, StreamType & out_stream, const StreamType & in_stream); @@ -376,6 +386,9 @@ private: void CopyTmpStreamToOutputStreams(Item::Function & fun, StreamType & ezc_out_tmp_stream, StreamType & previous_stream); + void CreateMsg(const wchar_t * type, const std::wstring & model_name, std::vector & fields, size_t how_many_fields_print, + const wchar_t * arg = nullptr, const wchar_t * arg2 = nullptr, const wchar_t * arg3 = nullptr); + void CreateMsg(const wchar_t * type, const std::wstring & model_name, std::vector & fields, const wchar_t * arg = nullptr, const wchar_t * arg2 = nullptr, const wchar_t * arg3 = nullptr); @@ -1245,106 +1258,149 @@ bool Generator::IsCurrentParam(std::vector & parameters) } + template -void Generator::CallSpace(morm::ModelWrapper & model_wrapper, pt::Space & root_space, FindHelper & find_helper, std::vector & fields, size_t field_index, - std::vector & parameters, StreamType & out_stream) +void Generator::CallSpaceObjectForLastField(std::vector & parameters, StreamType & out_stream, pt::Space * space) +{ + // should we convert the last value to last_res? + + if( ShouldMakeDump(parameters) ) + { + space->serialize_to_json_stream(out_stream); // we can add pretty print + } +} + + +template +pt::Space * Generator::CallSpaceObjectForMiddleField(std::wstring & root_space_name, std::vector & fields, size_t field_index, pt::Space * space) +{ + std::wstring & next_field = fields[field_index]; + space = space->get_object_field(next_field); + + if( !space ) + { + CreateMsg(L"cannot find space field: ", root_space_name, fields, field_index + 1); + } + + return space; +} + + + +template +void Generator::CallSpaceTableForLastField(morm::ModelWrapper & model_wrapper, std::vector & parameters, StreamType & out_stream, + pt::Space * space, size_t model_wrapper_space_table_index) +{ + pt::Space::TableType * table = space->get_table(); + + if( stack_tab[stack_index-1].is_for ) + { + // we are in [for...]statement, increment iterator and check the range + model_wrapper.increment_iterator(model_wrapper_space_table_index, table->size()); + size_t iterator_value = model_wrapper.get_space_iterator_value(model_wrapper_space_table_index); + last_res = (iterator_value < table->size()); + } + else + { + // we are not in [for..], it can be for example [if...], return true if the table is not empty + last_res = !table->empty(); + } + + if( ShouldMakeDump(parameters) ) + { + space->serialize_to_json_stream(out_stream); + } + + if( IsCurrentParam(parameters) ) + { + size_t iterator_value = model_wrapper.get_space_iterator_value(model_wrapper_space_table_index); + + if( iterator_value < table->size() ) + { + (*table)[iterator_value]->serialize_to_json_stream(out_stream); + } + } + +} + +template +pt::Space * Generator::CallSpaceTableForMiddleField(morm::ModelWrapper & model_wrapper, std::wstring & root_space_name, std::vector & fields, + size_t field_index, pt::Space * space, size_t model_wrapper_space_table_index) +{ + pt::Space::TableType * table = space->get_table(); + + // check the current iterator, if it is correct then select the item from the table + size_t iterator_value = model_wrapper.get_space_iterator_value(model_wrapper_space_table_index); + + if( iterator_value < table->size() ) + { + space = (*table)[iterator_value]; + } + else + { + CreateMsg(L"space table: ", root_space_name, fields, field_index, L" is not initialized, have you forgotten to use [for...] statement?"); + space = nullptr; + } + + return space; +} + + + +template +void Generator::CallSpace(morm::ModelWrapper & model_wrapper, pt::Space & root_space, FindHelper & find_helper, std::vector & fields, + size_t root_field_index, std::vector & parameters, StreamType & out_stream) { pt::Space * space = &root_space; last_res = false; - std::wstring * field = nullptr; + size_t field_index = root_field_index; - for(size_t i=field_index ; i < fields.size() + 1 ; ) + /* + * + * we are iterating through such objects: + * [root_space, fields[field_index], fields[field_index+1], fields[field_index+2], fields[field_index+3] ...] + * the first item is the root_space with a find_helper.fun_name name + * + */ + while( (field_index < fields.size() + 1) && space ) { - bool is_last_field = (i == fields.size()); - field = (i == 0) ? find_helper.fun_name : &fields[i - 1]; + bool is_last_field = (field_index == fields.size()); if( space->is_object() ) { if( is_last_field ) { - if( ShouldMakeDump(parameters) ) - { - space->serialize_to_json_stream(out_stream); // we can add pretty print - } + CallSpaceObjectForLastField(parameters, out_stream, space); } else { - pt::Space * old = space; - std::wstring & next_field = fields[i]; - space = space->get_object_field(next_field); - - if( !space ) - { - if( plog ) - { - (*plog) << pt::Log::log2 << "Ezc: there is no " << next_field << " property of object " << *field << pt::Log::logend; - } - - break; - } + space = CallSpaceObjectForMiddleField(*find_helper.fun_name, fields, field_index, space); } - ++i; + field_index += 1; } else if( space->is_table() ) { - pt::Space::TableType * table = space->get_table(); - size_t space_index = i - field_index; + size_t model_wrapper_space_table_index = field_index - root_field_index; - // add testing space_index range [0..MODEL_WRAPPER_SPACE_INDICES_TABLE_SIZE - 1] - - if( is_last_field ) + if( model_wrapper_space_table_index < model_wrapper.space_indices_table_size() ) { - if( stack_tab[stack_index-1].is_for ) + if( is_last_field ) { - // we are in [for...]statement, increment iterator and check the range - model_wrapper.increment_iterator(space_index, table->size()); - size_t iterator_value = model_wrapper.get_space_iterator_value(space_index); - last_res = (iterator_value < table->size()); + CallSpaceTableForLastField(model_wrapper, parameters, out_stream, space, model_wrapper_space_table_index); + field_index += 1; } else { - // we are not in [for..], it can be for example [if...], return true if the table is not empty - last_res = !table->empty(); + space = CallSpaceTableForMiddleField(model_wrapper, *find_helper.fun_name, fields, field_index, space, model_wrapper_space_table_index); + // don't increment field_index } - - if( ShouldMakeDump(parameters) ) - { - space->serialize_to_json_stream(out_stream); - } - - if( IsCurrentParam(parameters) ) - { - size_t iterator_value = model_wrapper.get_space_iterator_value(space_index); - - if( iterator_value < table->size() ) - { - (*table)[iterator_value]->serialize_to_json_stream(out_stream); - } - } - - ++i; } else { - // check the current iterator, if it is correct then select the item from the table - size_t iterator_value = model_wrapper.get_space_iterator_value(space_index); - last_res = (iterator_value < table->size()); - - if( last_res ) - { - space = (*table)[iterator_value]; - } - else - { - // IMPROVEME use CreateMsg() - if( plog ) - { - (*plog) << pt::Log::log1 << "Ezc: table: " << field << " is not initialized, have you forgotten to use [for...] statement?" << pt::Log::logend; - } - break; - } + CreateMsg(L"", *find_helper.fun_name, fields, field_index, L" exceeded the maximum number of fields for a space object"); + break; } } else @@ -1352,15 +1408,11 @@ void Generator::CallSpace(morm::ModelWrapper & model_wrapper, pt::Sp if( is_last_field ) { space->serialize_to_string(out_stream); - ++i; + field_index += 1; } else { - if( plog ) - { - (*plog) << pt::Log::log2 << "Ezc: " << (*field) << " is not a model not a model container nor a space" << pt::Log::logend; - } - + CreateMsg(L"", *find_helper.fun_name, fields, field_index, L" is not a model, model container nor a space"); break; } } @@ -1915,16 +1967,16 @@ void Generator::CreateMsg(const wchar_t * type, const wchar_t * arg) template -void Generator::CreateMsg(const wchar_t * type, const std::wstring & model_name, std::vector & fields, +void Generator::CreateMsg(const wchar_t * type, const std::wstring & model_name, std::vector & fields, size_t how_many_fields_print, const wchar_t * arg, const wchar_t * arg2, const wchar_t * arg3) { if( plog ) { (*plog) << pt::Log::log2 << L"Ezc: " << type << model_name; - for(std::wstring & str : fields) + for(size_t i=0 ; i < how_many_fields_print && i < fields.size() ; ++i) { - (*plog) << '.' << str; + (*plog) << '.' << fields[i]; } if( arg ) @@ -1947,6 +1999,16 @@ void Generator::CreateMsg(const wchar_t * type, const std::wstring & } +template +void Generator::CreateMsg(const wchar_t * type, const std::wstring & model_name, std::vector & fields, + const wchar_t * arg, const wchar_t * arg2, const wchar_t * arg3) +{ + + CreateMsg(type, model_name, fields, fields.size(), arg, arg2, arg3); +} + + + template void Generator::CreateMsg(const std::wstring & type, const std::wstring & arg) { From c2283f70d49dcf26efb7141327126b5cc872c7a7 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Sun, 27 Jun 2021 22:42:00 +0200 Subject: [PATCH 15/19] Generator when printing Model/Space is recognizing now such parameters: - "dump" or "dump_to_space" parameters to make a dump in Space format - "dump_to_json" parameter to make json dump - "pretty" parameter to make the dump pretty (with new lines and indents) --- src/generator.h | 101 +++++++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 44 deletions(-) diff --git a/src/generator.h b/src/generator.h index 93a98a3..fc5b61a 100644 --- a/src/generator.h +++ b/src/generator.h @@ -378,10 +378,14 @@ 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); - bool ShouldEscapeValue(std::vector & parameters); - bool ShouldMakeDump(std::vector & parameters); + + bool HasParam(std::vector & parameters, const wchar_t * param1, const wchar_t * param2 = nullptr); + bool ShouldMakeSpaceDump(std::vector & parameters); + bool ShouldMakeJsonDump(std::vector & parameters); + bool IsPrettyPrint(std::vector & parameters); bool IsCurrentParam(std::vector & parameters); + void DumpSpaceIfNeeded(std::vector & parameters, StreamType & out_stream, pt::Space * space); void CopyTmpStreamToOutputStreams(Item::Function & fun, StreamType & ezc_out_tmp_stream, StreamType & previous_stream); @@ -1203,33 +1207,14 @@ void Generator::CallObject(BaseObj & base_obj, int metho - template -bool Generator::ShouldEscapeValue(std::vector & parameters) +bool Generator::HasParam(std::vector & parameters, const wchar_t * param1, const wchar_t * param2) { for(Var & var : parameters) { if( !var.is_function ) { - if( var.str == L"raw" || var.str == L"noescape" ) - { - return false; - } - } - } - - return true; -} - - -template -bool Generator::ShouldMakeDump(std::vector & parameters) -{ - for(Var & var : parameters) - { - if( !var.is_function ) - { - if( var.str == L"dump" || var.str == L"to_str" ) + if( var.str == param1 || (param2 && var.str == param2) ) { return true; } @@ -1240,21 +1225,56 @@ bool Generator::ShouldMakeDump(std::vector & parameters) } + +template +bool Generator::ShouldMakeSpaceDump(std::vector & parameters) +{ + return HasParam(parameters, L"dump", L"dump_to_space"); +} + + +template +bool Generator::ShouldMakeJsonDump(std::vector & parameters) +{ + return HasParam(parameters, L"dump_to_json"); +} + + template bool Generator::IsCurrentParam(std::vector & parameters) { - for(Var & var : parameters) + return HasParam(parameters, L"current"); +} + + +template +bool Generator::IsPrettyPrint(std::vector & parameters) +{ + return HasParam(parameters, L"pretty"); +} + + + +template +void Generator::DumpSpaceIfNeeded(std::vector & parameters, StreamType & out_stream, pt::Space * space) +{ + bool dump_space = ShouldMakeSpaceDump(parameters); + bool dump_json = ShouldMakeJsonDump(parameters); + + if( dump_space || dump_json ) { - if( !var.is_function ) + bool pretty = IsPrettyPrint(parameters); + + if( dump_space ) { - if( var.str == L"current" ) - { - return true; - } + space->serialize_to_space_stream(out_stream, pretty); + } + else + if( dump_json ) + { + space->serialize_to_json_stream(out_stream, pretty); } } - - return false; } @@ -1262,12 +1282,8 @@ bool Generator::IsCurrentParam(std::vector & parameters) template void Generator::CallSpaceObjectForLastField(std::vector & parameters, StreamType & out_stream, pt::Space * space) { - // should we convert the last value to last_res? - - if( ShouldMakeDump(parameters) ) - { - space->serialize_to_json_stream(out_stream); // we can add pretty print - } + // CHECKME should we convert the last value to last_res? + DumpSpaceIfNeeded(parameters, out_stream, space); } @@ -1275,7 +1291,7 @@ template pt::Space * Generator::CallSpaceObjectForMiddleField(std::wstring & root_space_name, std::vector & fields, size_t field_index, pt::Space * space) { std::wstring & next_field = fields[field_index]; - space = space->get_object_field(next_field); + space = space->get_space(next_field); if( !space ) { @@ -1306,10 +1322,7 @@ void Generator::CallSpaceTableForLastField(morm::ModelWrapper & mode last_res = !table->empty(); } - if( ShouldMakeDump(parameters) ) - { - space->serialize_to_json_stream(out_stream); - } + DumpSpaceIfNeeded(parameters, out_stream, space); if( IsCurrentParam(parameters) ) { @@ -1317,7 +1330,7 @@ void Generator::CallSpaceTableForLastField(morm::ModelWrapper & mode if( iterator_value < table->size() ) { - (*table)[iterator_value]->serialize_to_json_stream(out_stream); + (*table)[iterator_value]->serialize_to_string(out_stream); } } @@ -1450,7 +1463,7 @@ bool Generator::CallModel(morm::Model & model, const std::wstring & if( found && !str.empty()) { - bool should_escape = ShouldEscapeValue(parameters); + bool should_escape = HasParam(parameters, L"raw", L"noescape"); CopyStream(str, out_stream, should_escape); } From acb42f453c22728a128a10bd6a2eed2c61c75ba1 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Tue, 29 Jun 2021 23:38:38 +0200 Subject: [PATCH 16/19] added support for two new ezc statements for clearing/trimming text nodes [ezc clear_all_white_nodes "yes"]...[end] - will clear a text node if the text consists of only white characters [ezc trim_text_nodes "yes"]...[end] - will trim text nodes (removes white characters at the beginning and at the end) "yes" is assumed by default if not present, also "no" can be specified to change the behavior --- src/generator.h | 8 +++ src/patternparser.cpp | 125 +++++++++++++++++++++++++++++++++++++----- src/patternparser.h | 22 +++++++- 3 files changed, 139 insertions(+), 16 deletions(-) diff --git a/src/generator.h b/src/generator.h index fc5b61a..cecbad6 100644 --- a/src/generator.h +++ b/src/generator.h @@ -2441,7 +2441,15 @@ template void Generator::MakeTextEzc(Item & item) { if( item.function.name == L"frame" ) + { MakeEzcFrame(item); + } + else + if( item.function.name == L"clear_all_white_nodes" || item.function.name == L"trim_text_nodes" ) + { + // text nodes are already cleared/trimmed by PatternParser + MakeTextContainer(item); + } // in the future we can use more builtin functions } diff --git a/src/patternparser.cpp b/src/patternparser.cpp index d82b623..7402133 100644 --- a/src/patternparser.cpp +++ b/src/patternparser.cpp @@ -136,6 +136,30 @@ void PatternParser::SetLogger(pt::Log * log) } +void PatternParser::InitializeEnvTab() +{ + env_tab.clear(); + + Env env; + env.clear_all_white_nodes = delete_white_text_items; + env_tab.push_back(env); +} + + +void PatternParser::IncreaseEnvTab() +{ + if( env_tab.empty() ) + { + InitializeEnvTab(); + } + else + { + env_tab.push_back(env_tab.back()); + } +} + + + void PatternParser::ParseFile(const std::string & file_name, Pattern & pattern) { ParseFile(file_name.c_str(), pattern); @@ -147,10 +171,13 @@ void PatternParser::ParseFile(const std::string & file_name, Pattern & pattern) void PatternParser::ParseFile(const char * file_name, Pattern & pattern) { pat = &pattern; + pat->Clear(); pt::utf8_to_wide(file_name, pat->item_root.file_name); include_level = 0; + InitializeEnvTab(); CreateTreeReadIncludeSkipAllowFlag(pat->item_root); + env_tab.clear(); } @@ -167,9 +194,13 @@ void PatternParser::ParseFile(const std::wstring & file_name, Pattern & pattern) void PatternParser::ParseFile(const wchar_t * file_name, Pattern & pattern) { pat = &pattern; + pat->Clear(); pat->item_root.file_name = file_name; include_level = 0; + InitializeEnvTab(); + CreateTreeReadIncludeSkipAllowFlag(pat->item_root); + env_tab.clear(); } @@ -194,11 +225,13 @@ void PatternParser::ParseString(const std::string & str, Pattern & pattern) void PatternParser::ParseString(const wchar_t * str, Pattern & pattern) { pat = &pattern; + pat->Clear(); itext = str; include_level = 0; + InitializeEnvTab(); - pat->item_root.Clear(); CreateTreeContainer(pat->item_root); + env_tab.clear(); } @@ -387,13 +420,7 @@ return *(itext++); bool PatternParser::IsWhite(wchar_t c) { - // 13 (\r) is from a dos file at the end of a line (\r\n) - // 160 is a non-breaking space - - if( c==' ' || c=='\t' || c==13 || c==160 || c==10 ) - return true; - -return false; + return pt::is_white(c, true, true); } @@ -425,7 +452,7 @@ size_t count = 1; void PatternParser::CheckWhiteAndDelete(std::wstring & s) { size_t i; - + if( s.empty() ) return; @@ -851,6 +878,9 @@ void PatternParser::ReadDirectiveFilter(Item & item) } + + + void PatternParser::ReadDirectiveEzc(Item & item) { item.type = Item::item_ezc; @@ -901,7 +931,53 @@ void PatternParser::ReadDirectiveReturn(Item & item) } +/* + * returns true if an Env struct has been added to env_tab + */ +bool PatternParser::CheckEnv(Item & item) +{ + if( item.function.name == L"clear_all_white_nodes" ) + { + IncreaseEnvTab(); + env_tab.back().clear_all_white_nodes = CheckEnvIsYesParameter(item); + return true; + } + if( item.function.name == L"trim_text_nodes" ) + { + IncreaseEnvTab(); + env_tab.back().trim_text_nodes = CheckEnvIsYesParameter(item); + return true; + } + + return false; +} + + +/* + * + * if no parameters are present then we assume the "yes" is by default + * + */ +bool PatternParser::CheckEnvIsYesParameter(Item & item) +{ + if( item.function.parameters.size() > 0 && !item.function.parameters[0]->is_function ) + { + std::wstring & name = item.function.parameters[0]->name; + + if( name == L"yes" || name == L"true" ) + { + return true; + } + else + if( name == L"no" || name == L"false" ) + { + return false; + } + } + + return true; +} void PatternParser::CreateTreeReadItemDirective(Item & item) @@ -947,8 +1023,20 @@ int c; while( (c = ReadCharInText()) != -1 ) item.text += static_cast(c); - if( delete_white_text_items ) - CheckWhiteAndDelete(item.text); + if( !env_tab.empty() ) + { + Env & env = env_tab.back(); + + if( env.clear_all_white_nodes ) + { + CheckWhiteAndDelete(item.text); + } + + if( env.trim_text_nodes ) + { + pt::trim_white(item.text, true, true); + } + } item.type = Item::item_text; } @@ -1199,7 +1287,7 @@ void PatternParser::CreateTreeReadBlock(Item & item) -void PatternParser::CreateTreeReadFor(Item & item) +void PatternParser::CreateTreeReadOneChild(Item & item) { Item * pitem = item.AddItem(); @@ -1228,22 +1316,29 @@ bool PatternParser::CreateTree(Item & item) } while( item.type == Item::item_comment || item.type == Item::item_block ); + bool reduce_env_tab = false; + + if(item.type == Item::item_ezc) + reduce_env_tab = CheckEnv(item); + // such container can be read in program mode if( item.type == Item::item_container ) CreateTreeContainer(item); if( item.type == Item::item_if ) - CreateTreeReadIf(item); + CreateTreeReadIf(item); // reads one child or two if [else] statement is present - // CHECK ME is it correct to check item_filter and item_ezc here and call CreateTreeReadFor? if( item.type == Item::item_for || item.type == Item::item_filter || item.type == Item::item_ezc ) - CreateTreeReadFor(item); + CreateTreeReadOneChild(item); if( item.type == Item::item_include ) CreateTreeReadInclude(item); + if( reduce_env_tab && !env_tab.empty() ) + env_tab.resize(env_tab.size() - 1); + return true; } diff --git a/src/patternparser.h b/src/patternparser.h index bab52f3..421d1ad 100644 --- a/src/patternparser.h +++ b/src/patternparser.h @@ -85,6 +85,21 @@ public: private: + struct Env + { + bool clear_all_white_nodes; + bool trim_text_nodes; + + Env() + { + clear_all_white_nodes = false; + trim_text_nodes = false; + } + + }; + + std::vector env_tab; + // the output object Pattern * pat; @@ -130,6 +145,8 @@ private: pt::Log * log; + void InitializeEnvTab(); + void IncreaseEnvTab(); void ReadFile(const std::wstring & name, std::wstring & result); void ReadFile(const wchar_t * name, std::wstring & result); @@ -175,6 +192,9 @@ private: void ReadDirectiveReturn(Item & item); void ReadNormalStatement(Item & item); + bool CheckEnv(Item & item); + bool CheckEnvIsYesParameter(Item & item); + void CreateTreeReadDirectiveExpression(Item & item, bool is_statement); bool CreateTreeCheckProgramDirective(Item & item); bool CreateTreeReadExpression(Item & item); @@ -185,7 +205,7 @@ private: bool CreateTreeReadItem(Item & item); void CreateTreeReadIf(Item & item); void CreateTreeReadBlock(Item & item); - void CreateTreeReadFor(Item & item); + void CreateTreeReadOneChild(Item & item); bool CreateTree(Item & item); void CreateTreeContainer(Item & item); void CreateTreeReadInclude(Item & item); From 849b3e9ecc50f817f1acf57da53df2912cfde1e9 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Thu, 1 Jul 2021 23:21:20 +0200 Subject: [PATCH 17/19] changed the way how we iterate through Models, instead of ModelWrapper now we have Wrapper which has pointers to: model, model container, space or date --- src/generator.h | 304 ++++++++++++++++++++++++++++++------------------ src/models.cpp | 48 +++++--- src/models.h | 49 +++++--- 3 files changed, 250 insertions(+), 151 deletions(-) diff --git a/src/generator.h b/src/generator.h index cecbad6..2cf3cdd 100644 --- a/src/generator.h +++ b/src/generator.h @@ -152,7 +152,8 @@ private: Var * variable; #ifdef EZC_HAS_MORM_LIBRARY - morm::ModelWrapper * model_wrapper; + morm::Wrapper * wrapper; + size_t field_index; #endif FindHelper() @@ -165,32 +166,13 @@ private: item_block = nullptr; variable = nullptr; - #ifdef EZC_HAS_MORM_LIBRARY - model_wrapper = nullptr; - #endif - } - }; - - #ifdef EZC_HAS_MORM_LIBRARY - - struct CallModelHelper - { - size_t field_index; - morm::ModelWrapper * model_wrapper; - morm::Model * model; - - - CallModelHelper() - { + wrapper = nullptr; field_index = 0; - model_wrapper = nullptr; - model = nullptr; +#endif } }; -#endif - struct BlockStack { @@ -331,23 +313,26 @@ private: void CallObject(BaseObj & base_obj, int method_index, FunInfo & info); + void PrintDate(pt::Date * date, std::vector parameters, StreamType & out_stream); + bool PrintDatePart(pt::Date * date, const std::wstring & field, std::vector parameters, StreamType & out_stream); + void CallSpaceObjectForLastField(std::vector & parameters, StreamType & out_stream, pt::Space * space); pt::Space * CallSpaceObjectForMiddleField(std::wstring & root_space_name, std::vector & fields, size_t field_index, pt::Space * space); - void CallSpaceTableForLastField(morm::ModelWrapper & model_wrapper, std::vector & parameters, StreamType & out_stream, + void CallSpaceTableForLastField(morm::SpaceWrapper & space_wrapper, std::vector & parameters, StreamType & out_stream, pt::Space * space, size_t model_wrapper_space_table_index); - pt::Space * CallSpaceTableForMiddleField(morm::ModelWrapper & model_wrapper, std::wstring & root_space_name, std::vector & fields, + pt::Space * CallSpaceTableForMiddleField(morm::SpaceWrapper & space_wrapper, std::wstring & root_space_name, std::vector & fields, size_t field_index, pt::Space * space, size_t model_wrapper_space_table_index); - void CallSpace(morm::ModelWrapper & model_wrapper, pt::Space & root_space, FindHelper & find_helper, std::vector & fields, - size_t root_field_index, std::vector & parameters, StreamType & out_stream); + void CallSpace(FindHelper & find_helper, std::vector & fields, std::vector & parameters, StreamType & out_stream); #ifdef EZC_HAS_MORM_LIBRARY - bool CallModel(morm::Model & model, const std::wstring & field, std::vector parameters, StreamType & out_stream, const StreamType & in_stream); - CallModelHelper FindLastModelWrapper(morm::ModelWrapper & models_base, std::vector & fields); - void CallModelWrapper(FindHelper & find_helper, std::vector & fields, std::vector parameters, StreamType & out_stream, const StreamType & in_stream); + bool CallModelField(morm::Model & model, const std::wstring & field, std::vector parameters, StreamType & out_stream, const StreamType & in_stream); + void CallModel(morm::Model & model, FindHelper & find_helper, std::vector & fields, std::vector parameters, StreamType & out_stream, const StreamType & in_stream); + void FindLastModelWrapper(FindHelper & find_helper, std::vector & fields); + void CallWrapper(FindHelper & find_helper, std::vector & fields, std::vector parameters, StreamType & out_stream, const StreamType & in_stream); #endif void CallObject(BaseObj & base_obj, @@ -386,6 +371,7 @@ private: bool IsCurrentParam(std::vector & parameters); void DumpSpaceIfNeeded(std::vector & parameters, StreamType & out_stream, pt::Space * space); + void DumpModelIfNeeded(morm::Model & model, std::vector & parameters, StreamType & out_stream); void CopyTmpStreamToOutputStreams(Item::Function & fun, StreamType & ezc_out_tmp_stream, StreamType & previous_stream); @@ -1031,11 +1017,11 @@ bool Generator::FindInModels(FindHelper & find_helper) { if( pmodels ) { - morm::ModelWrapper * m = pmodels->Find(*find_helper.fun_name); + morm::Wrapper * m = pmodels->Find(*find_helper.fun_name); if( m ) { - find_helper.model_wrapper = m; + find_helper.wrapper = m; return true; } } @@ -1278,6 +1264,71 @@ void Generator::DumpSpaceIfNeeded(std::vector & parameters, Str } +template +void Generator::DumpModelIfNeeded(morm::Model & model, std::vector & parameters, StreamType & out_stream) +{ + bool dump_space = ShouldMakeSpaceDump(parameters); + bool dump_json = ShouldMakeJsonDump(parameters); + + if( dump_space || dump_json ) + { + //bool pretty = IsPrettyPrint(parameters); + + if( dump_space ) + { + // not implemented yet + } + else + if( dump_json ) + { + // IMPLEMENT ME + // depends on the model_connector (flat connector) + // need to be made in a different way + pt::TextStream temp_str; + model.to_text(temp_str, false, false); + out_stream << temp_str; + } + } +} + + + +template +void Generator::PrintDate(pt::Date * date, std::vector parameters, StreamType & out_stream) +{ + // IMPROVEME + // check for different formats depending on parameters + + date->Serialize(out_stream); +} + + +template +bool Generator::PrintDatePart(pt::Date * date, const std::wstring & field, std::vector parameters, StreamType & out_stream) +{ + if( field == L"year" ) + out_stream << date->year; + else + if( field == L"month" ) + out_stream << date->month; + else + if( field == L"day" ) + out_stream << date->day; + else + if( field == L"hour" ) + out_stream << date->hour; + else + if( field == L"min" ) + out_stream << date->min; + else + if( field == L"sec" ) + out_stream << date->sec; + else + return false; + + return true; +} + template void Generator::CallSpaceObjectForLastField(std::vector & parameters, StreamType & out_stream, pt::Space * space) @@ -1304,7 +1355,7 @@ pt::Space * Generator::CallSpaceObjectForMiddleField(std::wstring & template -void Generator::CallSpaceTableForLastField(morm::ModelWrapper & model_wrapper, std::vector & parameters, StreamType & out_stream, +void Generator::CallSpaceTableForLastField(morm::SpaceWrapper & space_wrapper, std::vector & parameters, StreamType & out_stream, pt::Space * space, size_t model_wrapper_space_table_index) { pt::Space::TableType * table = space->get_table(); @@ -1312,8 +1363,8 @@ void Generator::CallSpaceTableForLastField(morm::ModelWrapper & mode if( stack_tab[stack_index-1].is_for ) { // we are in [for...]statement, increment iterator and check the range - model_wrapper.increment_iterator(model_wrapper_space_table_index, table->size()); - size_t iterator_value = model_wrapper.get_space_iterator_value(model_wrapper_space_table_index); + space_wrapper.increment_iterator(model_wrapper_space_table_index, table->size()); + size_t iterator_value = space_wrapper.get_space_iterator_value(model_wrapper_space_table_index); last_res = (iterator_value < table->size()); } else @@ -1326,7 +1377,7 @@ void Generator::CallSpaceTableForLastField(morm::ModelWrapper & mode if( IsCurrentParam(parameters) ) { - size_t iterator_value = model_wrapper.get_space_iterator_value(model_wrapper_space_table_index); + size_t iterator_value = space_wrapper.get_space_iterator_value(model_wrapper_space_table_index); if( iterator_value < table->size() ) { @@ -1337,13 +1388,13 @@ void Generator::CallSpaceTableForLastField(morm::ModelWrapper & mode } template -pt::Space * Generator::CallSpaceTableForMiddleField(morm::ModelWrapper & model_wrapper, std::wstring & root_space_name, std::vector & fields, +pt::Space * Generator::CallSpaceTableForMiddleField(morm::SpaceWrapper & space_wrapper, std::wstring & root_space_name, std::vector & fields, size_t field_index, pt::Space * space, size_t model_wrapper_space_table_index) { pt::Space::TableType * table = space->get_table(); // check the current iterator, if it is correct then select the item from the table - size_t iterator_value = model_wrapper.get_space_iterator_value(model_wrapper_space_table_index); + size_t iterator_value = space_wrapper.get_space_iterator_value(model_wrapper_space_table_index); if( iterator_value < table->size() ) { @@ -1359,14 +1410,13 @@ pt::Space * Generator::CallSpaceTableForMiddleField(morm::ModelWrapp } - template -void Generator::CallSpace(morm::ModelWrapper & model_wrapper, pt::Space & root_space, FindHelper & find_helper, std::vector & fields, - size_t root_field_index, std::vector & parameters, StreamType & out_stream) +void Generator::CallSpace(FindHelper & find_helper, std::vector & fields, std::vector & parameters, StreamType & out_stream) { - pt::Space * space = &root_space; + morm::SpaceWrapper * space_wrapper = find_helper.wrapper->space_wrapper; + pt::Space * space = space_wrapper->get_space(); last_res = false; - size_t field_index = root_field_index; + size_t field_index = find_helper.field_index; /* * @@ -1395,18 +1445,18 @@ void Generator::CallSpace(morm::ModelWrapper & model_wrapper, pt::Sp else if( space->is_table() ) { - size_t model_wrapper_space_table_index = field_index - root_field_index; + size_t model_wrapper_space_table_index = field_index - find_helper.field_index; - if( model_wrapper_space_table_index < model_wrapper.space_indices_table_size() ) + if( model_wrapper_space_table_index < space_wrapper->space_indices_table_size() ) { if( is_last_field ) { - CallSpaceTableForLastField(model_wrapper, parameters, out_stream, space, model_wrapper_space_table_index); + CallSpaceTableForLastField(*space_wrapper, parameters, out_stream, space, model_wrapper_space_table_index); field_index += 1; } else { - space = CallSpaceTableForMiddleField(model_wrapper, *find_helper.fun_name, fields, field_index, space, model_wrapper_space_table_index); + space = CallSpaceTableForMiddleField(*space_wrapper, *find_helper.fun_name, fields, field_index, space, model_wrapper_space_table_index); // don't increment field_index } } @@ -1437,7 +1487,7 @@ void Generator::CallSpace(morm::ModelWrapper & model_wrapper, pt::Sp #ifdef EZC_HAS_MORM_LIBRARY template -bool Generator::CallModel(morm::Model & model, const std::wstring & field, std::vector parameters, StreamType & out_stream, const StreamType & in_stream) +bool Generator::CallModelField(morm::Model & model, const std::wstring & field, std::vector parameters, StreamType & out_stream, const StreamType & in_stream) { /* * if 'field' is a POD type then 'str' will be used in get_raw_value() @@ -1471,124 +1521,152 @@ bool Generator::CallModel(morm::Model & model, const std::wstring & } +template +void Generator::CallModel(morm::Model & model, FindHelper & find_helper, std::vector & fields, + std::vector parameters, StreamType & out_stream, const StreamType & in_stream) +{ + if( find_helper.field_index == fields.size() ) + { + // all fields items are models or models containers + DumpModelIfNeeded(model, parameters, out_stream); + } + else + if( find_helper.field_index + 1 == fields.size() ) + { + // last field is not a model nor a models container + if( !CallModelField(model, fields[find_helper.field_index], parameters, out_stream, in_stream) ) + { + CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", unknown property ", fields[find_helper.field_index].c_str(), L" of a model object"); + } + } + else + { + 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"); + } +} + + template -typename Generator::CallModelHelper Generator::FindLastModelWrapper(morm::ModelWrapper & models_base, std::vector & fields) +void Generator::FindLastModelWrapper(FindHelper & find_helper, std::vector & fields) { - CallModelHelper helper; - helper.field_index = 0; - helper.model_wrapper = &models_base; - helper.model = nullptr; - - for(; helper.field_index < fields.size() && !helper.model_wrapper->get_space() ; ++helper.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[helper.field_index]; - morm::ModelWrapper * child_model_wrapper = helper.model_wrapper->find_child(field); + std::wstring & field = fields[find_helper.field_index]; + morm::Wrapper * child_wrapper = find_helper.wrapper->find_child(field); - if( !child_model_wrapper ) + if( !child_wrapper ) { - helper.model = helper.model_wrapper->get_model(); - // this can return null for lists/vectors in a case when the iterator is not pointing to a valid item + morm::Model * model = nullptr; - if( helper.model ) + if( find_helper.wrapper->model ) { - child_model_wrapper = helper.model->get_model_wrapper(nullptr, field.c_str(), false); + model = find_helper.wrapper->model; + } + else + if( find_helper.wrapper->model_container_wrapper ) + { + model = find_helper.wrapper->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( child_model_wrapper ) + if( model ) + { + morm::Wrapper new_wrapper = model->get_wrapper(nullptr, field.c_str()); + + if( new_wrapper.has_object() ) { - helper.model_wrapper->add_child(field, child_model_wrapper); + child_wrapper = find_helper.wrapper->add_child(field, new_wrapper); } } } - if( !child_model_wrapper ) + if( !child_wrapper ) break; - helper.model_wrapper = child_model_wrapper; - helper.model = nullptr; + find_helper.wrapper = child_wrapper; } - - return helper; } template -void Generator::CallModelWrapper(FindHelper & find_helper, std::vector & fields, +void Generator::CallWrapper(FindHelper & find_helper, std::vector & fields, std::vector parameters, StreamType & out_stream, const StreamType & in_stream) { last_res = false; - CallModelHelper helper = FindLastModelWrapper(*find_helper.model_wrapper, fields); + FindLastModelWrapper(find_helper, fields); // if: - // helper.field_index == fields.size() - all fields items are models or models containers - // helper.field_index == fields.size()-1 - last field is not a model nor a models container - // helper.field_index < fields.size()-1 - incorrect + // helper.field_index == fields.size() - all fields items are either models, models containers, space or a date + // helper.field_index == fields.size()-1 - only the last field is not known + // helper.field_index < fields.size()-1 - there are more not known fields - //morm::Model * model = helper.model_wrapper->get_model(); - pt::Space * space = helper.model_wrapper->get_space(); + bool all_fields_known = (find_helper.field_index == fields.size()); + bool last_field_not_known = (find_helper.field_index + 1 == fields.size()); - if( helper.field_index + 1 < fields.size() ) + if( find_helper.wrapper->space_wrapper ) { - if( space ) + CallSpace(find_helper, fields, parameters, out_stream); + } + + if( find_helper.wrapper->date ) + { + if( all_fields_known ) { - CallSpace(*helper.model_wrapper, *space, find_helper, fields, helper.field_index, parameters, out_stream); + PrintDate(find_helper.wrapper->date, parameters, out_stream); } else + if( last_field_not_known ) { - CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", ", fields[helper.field_index].c_str(), L" is not a model nor a model container nor a space"); - last_res = false; - } - } - else - if( helper.field_index + 1 == fields.size() ) - { - // last field is not a model nor a models container - - if( helper.model ) - { - if( !CallModel(*helper.model, fields[helper.field_index], parameters, out_stream, in_stream) ) + // last field is not a model nor a models container + if( !PrintDatePart(find_helper.wrapper->date, fields[find_helper.field_index], parameters, out_stream) ) { - CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", unknown ", fields[helper.field_index].c_str()); + CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", unknown property ", fields[find_helper.field_index].c_str(), L" of date object"); } } else - if( space ) { - CallSpace(*helper.model_wrapper, *space, find_helper, fields, helper.field_index, parameters, out_stream); - } - else - { - last_res = false; - CreateMsg(L"model ", *find_helper.fun_name, fields, L" is not initialized, have you forgotten to use [for ...] statement?"); // a different msg if we are using Space? + 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"); } } - else - { - // all fields items are models or models containers or last one is Space - // this is usualy in [for...] or [if ...] statements - if( space ) + if( find_helper.wrapper->model ) + { + CallModel(*find_helper.wrapper->model, find_helper, fields, parameters, out_stream, in_stream); + } + + if( find_helper.wrapper->model_container_wrapper ) + { + morm::Model * model = find_helper.wrapper->model_container_wrapper->get_model(); + + if( model ) { - CallSpace(*helper.model_wrapper, *space, find_helper, fields, helper.field_index, parameters, out_stream); + CallModel(*model, find_helper, fields, parameters, out_stream, in_stream); } else + { + if( last_field_not_known ) + { + CreateMsg(L"model ", *find_helper.fun_name, fields, L" is not initialized, have you forgotten to use [for ...] statement?"); + } + } + + if( all_fields_known ) { if( stack_tab[stack_index-1].is_for ) { - // helper.model_wrapper is always set - helper.model_wrapper->increment_iterator(); - helper.model_wrapper->clear_childs(); - last_res = helper.model_wrapper->is_iterator_correct(); + find_helper.wrapper->model_container_wrapper->increment_iterator(); + find_helper.wrapper->clear_childs(); + last_res = find_helper.wrapper->model_container_wrapper->is_iterator_correct(); } else { - last_res = !helper.model_wrapper->is_container_empty(); + last_res = !find_helper.wrapper->model_container_wrapper->is_container_empty(); } - - // add support for "dump" parameter } } } + #endif @@ -1714,8 +1792,8 @@ std::vector parameters; } #ifdef EZC_HAS_MORM_LIBRARY - if( find_helper.model_wrapper ) - CallModelWrapper(find_helper, item_fun.fields, parameters, out_stream, in_stream); + if( find_helper.wrapper ) + CallWrapper(find_helper, item_fun.fields, parameters, out_stream, in_stream); else #endif if( find_helper.base_obj ) diff --git a/src/models.cpp b/src/models.cpp index a2fb8b4..bafe313 100644 --- a/src/models.cpp +++ b/src/models.cpp @@ -59,15 +59,6 @@ Models::~Models() void Models::Clear() { - for(auto & map_item : models_map) - { - if( map_item.second->should_be_auto_removed() ) - { - delete map_item.second; - map_item.second = nullptr; - } - } - models_map.clear(); } @@ -75,40 +66,59 @@ void Models::Clear() void Models::Add(const std::wstring & name, morm::Model & model) { - morm::ModelWrapper * model_wrapper = new morm::ModelWrapperModel(&model); - models_map[name] = model_wrapper; + morm::Wrapper wrapper; + wrapper.model = &model; + models_map[name] = wrapper; } void Models::Add(const std::wstring & name, morm::Model * model) { - morm::ModelWrapper * model_wrapper = new morm::ModelWrapperModel(model); - models_map[name] = model_wrapper; + morm::Wrapper wrapper; + wrapper.model = model; + models_map[name] = wrapper; } void Models::Add(const std::wstring & name, pt::Space & space) { - morm::ModelWrapper * model_wrapper = new morm::ModelWrapperSpace(&space); - models_map[name] = model_wrapper; + morm::Wrapper wrapper; + wrapper.space_wrapper = new morm::SpaceWrapper(&space); + models_map[name] = wrapper; } void Models::Add(const std::wstring & name, pt::Space * space) { - morm::ModelWrapper * model_wrapper = new morm::ModelWrapperSpace(space); - models_map[name] = model_wrapper; + morm::Wrapper wrapper; + wrapper.space_wrapper = new morm::SpaceWrapper(space); + models_map[name] = wrapper; } +void Models::Add(const std::wstring & name, pt::Date & date) +{ + morm::Wrapper wrapper; + wrapper.date = &date; + models_map[name] = wrapper; +} -morm::ModelWrapper * Models::Find(const std::wstring & name) + +void Models::Add(const std::wstring & name, pt::Date * date) +{ + morm::Wrapper wrapper; + wrapper.date = date; + models_map[name] = wrapper; +} + + +morm::Wrapper * Models::Find(const std::wstring & name) { auto iterator = models_map.find(name); if( iterator != models_map.end() ) { - return iterator->second; + return &iterator->second; } return nullptr; diff --git a/src/models.h b/src/models.h index 61204d9..0ae2078 100644 --- a/src/models.h +++ b/src/models.h @@ -40,7 +40,7 @@ #ifdef EZC_HAS_MORM_LIBRARY -#include "modelwrapper.h" +#include "wrapper.h" #include "funinfo.h" #include "space/space.h" @@ -62,69 +62,80 @@ public: void Add(const std::wstring & name, pt::Space & space); void Add(const std::wstring & name, pt::Space * space); + void Add(const std::wstring & name, pt::Date & space); + void Add(const std::wstring & name, pt::Date * space); + template void Add(const std::wstring & name, std::vector & container) { - morm::ModelWrapper * model_wrapper = new morm::ModelWrapperVector(&container); - models_map[name] = model_wrapper; + morm::Wrapper wrapper; + wrapper.model_container_wrapper = new morm::ModelWrapperVector(&container); + models_map[name] = wrapper; } template void Add(const std::wstring & name, std::vector * container) { - morm::ModelWrapper * model_wrapper = new morm::ModelWrapperVector(container); - models_map[name] = model_wrapper; + morm::Wrapper wrapper; + wrapper.model_container_wrapper = new morm::ModelWrapperVector(container); + models_map[name] = wrapper; } template void Add(const std::wstring & name, std::vector & container) { - morm::ModelWrapper * model_wrapper = new morm::ModelWrapperVectorPointer(&container); - models_map[name] = model_wrapper; + morm::Wrapper wrapper; + wrapper.model_container_wrapper = new morm::ModelWrapperVectorPointer(&container); + models_map[name] = wrapper; } template void Add(const std::wstring & name, std::vector * container) { - morm::ModelWrapper * model_wrapper = new morm::ModelWrapperVectorPointer(container); - models_map[name] = model_wrapper; + morm::Wrapper wrapper; + wrapper.model_container_wrapper = new morm::ModelWrapperVectorPointer(container); + models_map[name] = wrapper; } template void Add(const std::wstring & name, std::list & container) { - morm::ModelWrapper * model_wrapper = new morm::ModelWrapperList(&container); - models_map[name] = model_wrapper; + morm::Wrapper wrapper; + wrapper.model_container_wrapper = new morm::ModelWrapperList(&container); + models_map[name] = wrapper; } template void Add(const std::wstring & name, std::list * container) { - morm::ModelWrapper * model_wrapper = new morm::ModelWrapperList(container); - models_map[name] = model_wrapper; + morm::Wrapper wrapper; + wrapper.model_container_wrapper = new morm::ModelWrapperList(container); + models_map[name] = wrapper; } template void Add(const std::wstring & name, std::list & container) { - morm::ModelWrapper * model_wrapper = new morm::ModelWrapperListPointer(&container); - models_map[name] = model_wrapper; + morm::Wrapper wrapper; + wrapper.model_container_wrapper = new morm::ModelWrapperListPointer(&container); + models_map[name] = wrapper; } template void Add(const std::wstring & name, std::list * container) { - morm::ModelWrapper * model_wrapper = new morm::ModelWrapperListPointer(container); - models_map[name] = model_wrapper; + morm::Wrapper wrapper; + wrapper.model_container_wrapper = new morm::ModelWrapperListPointer(container); + models_map[name] = wrapper; } - morm::ModelWrapper * Find(const std::wstring & name); + morm::Wrapper * Find(const std::wstring & name); void Clear(); protected: - std::map models_map; + std::map models_map; }; From 995cccdacef4b5d114daeebf5769864832bc0a9a Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Fri, 2 Jul 2021 20:23:20 +0200 Subject: [PATCH 18/19] add two new ezc statements: [if-def ...] and [if-not-def ...] [if-def my_function] returns true if my_function is defined somewhere (either a model, model container, space, date, block, function or variable) add support for "noescape" or "raw" parameters to Space fields fixed: CallWrapper() didn't return a status if a model/space/date/container was found --- src/funinfo.h | 9 +- src/generator.h | 415 +++++++++++++++++++++++++++++------------- src/item.h | 2 +- src/patternparser.cpp | 33 +++- src/patternparser.h | 2 + 5 files changed, 333 insertions(+), 128 deletions(-) diff --git a/src/funinfo.h b/src/funinfo.h index 18e5a44..606e9c0 100644 --- a/src/funinfo.h +++ b/src/funinfo.h @@ -172,9 +172,14 @@ struct FunInfo bool is_for; // indicates that this function is from [if ...] statement - // it is true for all kind of if's: if-one, if-any, if-no.... bool is_if; + // indicates that this function is from [if-def ...] statement + bool is_if_def; + + // indicates that this function is from [if-not-def ...] statement + bool is_if_not_def; + // indicates that this funcion is a normal statement e.g.: [funcion_name] bool is_normal; @@ -221,6 +226,8 @@ struct FunInfo res = false; // result is false by default is_for = false; is_if = false; + is_if_def = false; + is_if_not_def = false; is_normal = false; is_filter = false; iter = 0; diff --git a/src/generator.h b/src/generator.h index 2cf3cdd..a34664d 100644 --- a/src/generator.h +++ b/src/generator.h @@ -242,6 +242,8 @@ private: // true if the Generator is working with [for ...], [if ...] etc. bool is_generating_for; bool is_generating_if; + bool is_generating_if_def; + bool is_generating_if_not_def; bool is_generating_normal; bool is_generating_filter; @@ -259,7 +261,6 @@ private: ExpressionParser * expression_parser; - void ResizeStreamStack(std::vector & stream_tab, size_t stream_tab_max_size); void ResizeFilterTab(); void ResizeStack(); @@ -285,6 +286,7 @@ private: template CharType ToLower(CharType c); + bool IsTestingFunctionExistence(); bool CheckBlockArgument(int arg_index, FindHelper & find_helper); @@ -295,11 +297,11 @@ private: #endif bool FindInFunctionsAndBlocks(const std::wstring & name, FindHelper & find_helper); - bool FindInVariables(const std::wstring & name, FindHelper & find_helper); - bool Find(Item::Function & item_fun, FindHelper & find_helper); + void PrepareEnvStruct(FunInfo & info); + void CallFunction(typename Functions::UserFunction & function, FunInfo & info); void CallFunction(typename Functions::UserFunction & function, @@ -316,8 +318,10 @@ private: void PrintDate(pt::Date * date, std::vector parameters, StreamType & out_stream); bool PrintDatePart(pt::Date * date, const std::wstring & field, std::vector parameters, StreamType & out_stream); - void CallSpaceObjectForLastField(std::vector & parameters, StreamType & out_stream, pt::Space * space); + bool CallDate(FindHelper & find_helper, std::vector & fields, std::vector parameters, StreamType & out_stream); + void PrintLastSpaceField(pt::Space * space, std::vector & parameters, StreamType & out_stream); + void CallSpaceObjectForLastField(std::vector & parameters, StreamType & out_stream, pt::Space * space); pt::Space * CallSpaceObjectForMiddleField(std::wstring & root_space_name, std::vector & fields, size_t field_index, pt::Space * space); void CallSpaceTableForLastField(morm::SpaceWrapper & space_wrapper, std::vector & parameters, StreamType & out_stream, @@ -326,13 +330,13 @@ private: pt::Space * CallSpaceTableForMiddleField(morm::SpaceWrapper & space_wrapper, std::wstring & root_space_name, std::vector & fields, size_t field_index, pt::Space * space, size_t model_wrapper_space_table_index); - void CallSpace(FindHelper & find_helper, std::vector & fields, std::vector & parameters, StreamType & out_stream); + bool CallSpace(FindHelper & find_helper, std::vector & fields, std::vector & parameters, StreamType & out_stream); #ifdef EZC_HAS_MORM_LIBRARY bool CallModelField(morm::Model & model, const std::wstring & field, std::vector parameters, StreamType & out_stream, const StreamType & in_stream); - void CallModel(morm::Model & model, FindHelper & find_helper, std::vector & fields, std::vector parameters, StreamType & out_stream, const StreamType & in_stream); + bool CallModel(morm::Model & model, FindHelper & find_helper, std::vector & fields, std::vector parameters, StreamType & out_stream, const StreamType & in_stream); void FindLastModelWrapper(FindHelper & find_helper, std::vector & fields); - void CallWrapper(FindHelper & find_helper, std::vector & fields, std::vector parameters, StreamType & out_stream, const StreamType & in_stream); + bool CallWrapper(FindHelper & find_helper, std::vector & fields, std::vector parameters, StreamType & out_stream, const StreamType & in_stream); #endif void CallObject(BaseObj & base_obj, @@ -392,6 +396,8 @@ private: void MakeTextIf_go(Item & item, bool result); void MakeTextIf(Item & item); + void MakeTextIfDef(Item & item); + void MakeTextIfNotDef(Item & item); void MakeTextFor(Item & item); void MakeItemText(Item & item); void MakeTextContainer(Item & item); @@ -677,8 +683,6 @@ void Generator::ResizeBlockStack() - - template void Generator::ClearStreamStack(std::vector & stream_tab) { @@ -956,6 +960,12 @@ void Generator::Generate(OutStreams & out_streams) } +template +bool Generator::IsTestingFunctionExistence() +{ + return is_generating_if_def || is_generating_if_not_def; +} + template bool Generator::CheckBlockArgument(int arg_index, FindHelper & find_helper) @@ -1102,7 +1112,7 @@ bool Generator::Find(Item::Function & item_fun, FindHelper & find_he if( FindInModels(find_helper) ) return true; - if( !item_fun.fields.empty() ) + if( !item_fun.fields.empty() && !IsTestingFunctionExistence() ) { CreateMsg(L"unknown model", find_helper.fun_name->c_str()); return false; @@ -1122,27 +1132,36 @@ bool Generator::Find(Item::Function & item_fun, FindHelper & find_he if( FindInVariables(*find_helper.fun_name, find_helper) ) return true; - CreateMsg(L"unknown function", find_helper.fun_name->c_str()); + if( !IsTestingFunctionExistence() ) + CreateMsg(L"unknown function", find_helper.fun_name->c_str()); + return false; } +template +void Generator::PrepareEnvStruct(FunInfo & info) +{ + info.Clear(); + + info.is_for = is_generating_for; + info.is_if = is_generating_if; + info.is_if_def = is_generating_if_def; + info.is_if_not_def = is_generating_if_not_def; + info.is_normal = is_generating_normal; + info.is_filter = is_generating_filter; + info.iter = info.stack.iter; + info.stack_tab = stack_tab.data(); + info.stack_index = stack_index-1; +} + + template void Generator::CallFunction(typename Functions::UserFunction & function, FunInfo & info) { - info.Clear(); - - info.is_for = is_generating_for; - info.is_if = is_generating_if; - info.is_normal = is_generating_normal; - info.is_filter = is_generating_filter; - info.iter = info.stack.iter; - info.stack_tab = stack_tab.data(); - info.stack_index = stack_index-1; - + PrepareEnvStruct(info); (function)(info); - last_res = info.res; } @@ -1154,39 +1173,29 @@ void Generator::CallFunction(typename Functions::UserFun StreamType & out_stream, const StreamType & in_stream) { - if( parameters.empty() ) + if( !IsTestingFunctionExistence() ) { - FunInfo info(out_stream, parameters, empty, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item); - CallFunction(function, info); - } - else - { - FunInfo info(out_stream, parameters, parameters[0].str, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item); - CallFunction(function, info); + if( parameters.empty() ) + { + FunInfo info(out_stream, parameters, empty, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item); + CallFunction(function, info); + } + else + { + FunInfo info(out_stream, parameters, parameters[0].str, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item); + CallFunction(function, info); + } } } - - - template void Generator::CallObject(BaseObj & base_obj, int method_index, FunInfo & info) { - info.Clear(); - - info.is_for = is_generating_for; - info.is_if = is_generating_if; - info.is_normal = is_generating_normal; - info.is_filter = is_generating_filter; - info.iter = info.stack.iter; - info.stack_tab = stack_tab.data(); - info.stack_index = stack_index-1; - + PrepareEnvStruct(info); base_obj.CallFun(method_index, info); - last_res = info.res; } @@ -1306,35 +1315,100 @@ void Generator::PrintDate(pt::Date * date, std::vector paramete template bool Generator::PrintDatePart(pt::Date * date, const std::wstring & field, std::vector parameters, StreamType & out_stream) { + bool is_test = IsTestingFunctionExistence(); + if( field == L"year" ) - out_stream << date->year; + { + if( !is_test ) + out_stream << date->year; + } else if( field == L"month" ) - out_stream << date->month; + { + if( !is_test ) + out_stream << date->month; + } else if( field == L"day" ) - out_stream << date->day; + { + if( !is_test ) + out_stream << date->day; + } else if( field == L"hour" ) - out_stream << date->hour; + { + if( !is_test ) + out_stream << date->hour; + } else if( field == L"min" ) - out_stream << date->min; + { + if( !is_test ) + out_stream << date->min; + } else if( field == L"sec" ) - out_stream << date->sec; + { + if( !is_test ) + out_stream << date->sec; + } else + { return false; + } return true; } +template +bool Generator::CallDate(FindHelper & find_helper, std::vector & fields, std::vector parameters, StreamType & out_stream) +{ + 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()); + + if( all_fields_known ) + { + PrintDate(find_helper.wrapper->date, parameters, out_stream); + } + else + if( last_field_not_known ) + { + if( !PrintDatePart(find_helper.wrapper->date, fields[find_helper.field_index], parameters, out_stream) ) + { + 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; + } + } + 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 = false; + } + + return found; +} + + + + template void Generator::CallSpaceObjectForLastField(std::vector & parameters, StreamType & out_stream, pt::Space * space) { - // CHECKME should we convert the last value to last_res? - DumpSpaceIfNeeded(parameters, out_stream, space); + if( !IsTestingFunctionExistence() ) + { + // CHECKME should we convert the last value to last_res? + DumpSpaceIfNeeded(parameters, out_stream, space); + } } @@ -1344,7 +1418,7 @@ pt::Space * Generator::CallSpaceObjectForMiddleField(std::wstring & std::wstring & next_field = fields[field_index]; space = space->get_space(next_field); - if( !space ) + if( !space && !IsTestingFunctionExistence() ) { CreateMsg(L"cannot find space field: ", root_space_name, fields, field_index + 1); } @@ -1360,7 +1434,7 @@ void Generator::CallSpaceTableForLastField(morm::SpaceWrapper & spac { pt::Space::TableType * table = space->get_table(); - if( stack_tab[stack_index-1].is_for ) + if( is_generating_for ) { // we are in [for...]statement, increment iterator and check the range space_wrapper.increment_iterator(model_wrapper_space_table_index, table->size()); @@ -1370,23 +1444,27 @@ void Generator::CallSpaceTableForLastField(morm::SpaceWrapper & spac else { // we are not in [for..], it can be for example [if...], return true if the table is not empty + // if we are in [if-def...] - then last_res is set later in MakeTextIfDef(Item & item) when Call() method returns last_res = !table->empty(); } - DumpSpaceIfNeeded(parameters, out_stream, space); - - if( IsCurrentParam(parameters) ) + if( !IsTestingFunctionExistence() ) { - size_t iterator_value = space_wrapper.get_space_iterator_value(model_wrapper_space_table_index); + DumpSpaceIfNeeded(parameters, out_stream, space); - if( iterator_value < table->size() ) + if( IsCurrentParam(parameters) ) { - (*table)[iterator_value]->serialize_to_string(out_stream); + size_t iterator_value = space_wrapper.get_space_iterator_value(model_wrapper_space_table_index); + + if( iterator_value < table->size() ) + { + (*table)[iterator_value]->serialize_to_string(out_stream); + } } } - } + template pt::Space * Generator::CallSpaceTableForMiddleField(morm::SpaceWrapper & space_wrapper, std::wstring & root_space_name, std::vector & fields, size_t field_index, pt::Space * space, size_t model_wrapper_space_table_index) @@ -1402,6 +1480,7 @@ pt::Space * Generator::CallSpaceTableForMiddleField(morm::SpaceWrapp } else { + // this message can be print even for [if-def...] CreateMsg(L"space table: ", root_space_name, fields, field_index, L" is not initialized, have you forgotten to use [for...] statement?"); space = nullptr; } @@ -1411,7 +1490,26 @@ pt::Space * Generator::CallSpaceTableForMiddleField(morm::SpaceWrapp template -void Generator::CallSpace(FindHelper & find_helper, std::vector & fields, std::vector & parameters, StreamType & out_stream) +void Generator::PrintLastSpaceField(pt::Space * space, std::vector & parameters, StreamType & out_stream) +{ + bool no_escape = HasParam(parameters, L"raw", L"noescape"); + + if( no_escape ) + { + pt::WTextStream str; + space->serialize_to_string(str); + CopyStream(str, out_stream, false); + } + else + { + space->serialize_to_string(out_stream); + } +} + + + +template +bool Generator::CallSpace(FindHelper & find_helper, std::vector & fields, std::vector & parameters, StreamType & out_stream) { morm::SpaceWrapper * space_wrapper = find_helper.wrapper->space_wrapper; pt::Space * space = space_wrapper->get_space(); @@ -1463,23 +1561,33 @@ void Generator::CallSpace(FindHelper & find_helper, std::vectorserialize_to_string(out_stream); + if( !IsTestingFunctionExistence() ) + { + PrintLastSpaceField(space, parameters, out_stream); + } + field_index += 1; } else { - CreateMsg(L"", *find_helper.fun_name, fields, field_index, L" is not a model, model container nor a space"); - break; + if( !IsTestingFunctionExistence() ) + { + CreateMsg(L"", *find_helper.fun_name, fields, field_index, L" of a space is not an object nor a table"); + } + + space = nullptr; } } } + + return space != nullptr; } @@ -1513,8 +1621,8 @@ bool Generator::CallModelField(morm::Model & model, const std::wstri if( found && !str.empty()) { - bool should_escape = HasParam(parameters, L"raw", L"noescape"); - CopyStream(str, out_stream, should_escape); + bool no_escape = HasParam(parameters, L"raw", L"noescape"); + CopyStream(str, out_stream, !no_escape); } return found; @@ -1522,13 +1630,18 @@ bool Generator::CallModelField(morm::Model & model, const std::wstri template -void Generator::CallModel(morm::Model & model, FindHelper & find_helper, std::vector & fields, - std::vector parameters, StreamType & out_stream, const StreamType & in_stream) +bool Generator::CallModel(morm::Model & model, FindHelper & find_helper, std::vector & fields, + std::vector parameters, StreamType & out_stream, const StreamType & in_stream) { + bool found = true; + if( find_helper.field_index == fields.size() ) { // all fields items are models or models containers - DumpModelIfNeeded(model, parameters, out_stream); + if( !IsTestingFunctionExistence() ) + { + DumpModelIfNeeded(model, parameters, out_stream); + } } else if( find_helper.field_index + 1 == fields.size() ) @@ -1536,13 +1649,25 @@ void Generator::CallModel(morm::Model & model, FindHelper & find_hel // last field is not a model nor a models container if( !CallModelField(model, fields[find_helper.field_index], parameters, out_stream, in_stream) ) { - CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", unknown property ", fields[find_helper.field_index].c_str(), L" of a model object"); + if( !IsTestingFunctionExistence() ) + { + CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", unknown property ", fields[find_helper.field_index].c_str(), L" of a model object"); + } + + found = false; } } else { - 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"); + 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 = false; } + + return found; } @@ -1590,9 +1715,10 @@ void Generator::FindLastModelWrapper(FindHelper & find_helper, std:: template -void Generator::CallWrapper(FindHelper & find_helper, std::vector & fields, +bool Generator::CallWrapper(FindHelper & find_helper, std::vector & fields, std::vector parameters, StreamType & out_stream, const StreamType & in_stream) { + bool found = true; last_res = false; FindLastModelWrapper(find_helper, fields); @@ -1606,33 +1732,17 @@ void Generator::CallWrapper(FindHelper & find_helper, std::vectorspace_wrapper ) { - CallSpace(find_helper, fields, parameters, out_stream); + found = CallSpace(find_helper, fields, parameters, out_stream); } if( find_helper.wrapper->date ) { - if( all_fields_known ) - { - PrintDate(find_helper.wrapper->date, parameters, out_stream); - } - else - if( last_field_not_known ) - { - // last field is not a model nor a models container - if( !PrintDatePart(find_helper.wrapper->date, fields[find_helper.field_index], parameters, out_stream) ) - { - CreateMsg(L"cannot find ", *find_helper.fun_name, fields, L", unknown property ", fields[find_helper.field_index].c_str(), L" of date object"); - } - } - else - { - 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 = CallDate(find_helper, fields, parameters, out_stream); } if( find_helper.wrapper->model ) { - CallModel(*find_helper.wrapper->model, find_helper, fields, parameters, out_stream, in_stream); + found = CallModel(*find_helper.wrapper->model, find_helper, fields, parameters, out_stream, in_stream); } if( find_helper.wrapper->model_container_wrapper ) @@ -1641,19 +1751,21 @@ void Generator::CallWrapper(FindHelper & find_helper, std::vectormodel_container_wrapper->increment_iterator(); find_helper.wrapper->clear_childs(); @@ -1661,10 +1773,13 @@ void Generator::CallWrapper(FindHelper & find_helper, std::vectormodel_container_wrapper->is_container_empty(); } } } + + return found; } #endif @@ -1678,15 +1793,18 @@ void Generator::CallObject(BaseObj & base_obj, StreamType & out_stream, const StreamType & in_stream) { - if( parameters.empty() ) + if( !IsTestingFunctionExistence() ) { - FunInfo info(out_stream, parameters, empty, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item); - CallObject(base_obj, method_index, info); - } - else - { - FunInfo info(out_stream, parameters, parameters[0].str, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item); - CallObject(base_obj, method_index, info); + if( parameters.empty() ) + { + FunInfo info(out_stream, parameters, empty, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item); + CallObject(base_obj, method_index, info); + } + else + { + FunInfo info(out_stream, parameters, parameters[0].str, in_stream, stack_tab[stack_index-1], *stack_tab[stack_index-1].item); + CallObject(base_obj, method_index, info); + } } } @@ -1703,24 +1821,27 @@ bool Generator::CallBlock(Item & item_block, return false; } - StreamType * old_stream = output_stream; - BlockStack & block_stack = block_stack_tab[block_stack_index]; + if( !IsTestingFunctionExistence() ) + { + StreamType * old_stream = output_stream; + BlockStack & block_stack = block_stack_tab[block_stack_index]; - block_stack.was_return = false; - block_stack.args = parameters; + block_stack.was_return = false; + block_stack.args = parameters; - output_stream = block_stack.out_stream; - ClearStream(*output_stream); - block_stack_index += 1; + output_stream = block_stack.out_stream; + ClearStream(*output_stream); + block_stack_index += 1; - MakeText(item_block); + MakeText(item_block); - CopyStream(*output_stream, out_stream); - // last_res is set by [return ...] statement or other last evaluated function + CopyStream(*output_stream, out_stream); + // last_res is set by [return ...] statement or other last evaluated function - ClearStream(*output_stream); - output_stream = old_stream; - block_stack_index -= 1; + ClearStream(*output_stream); + output_stream = old_stream; + block_stack_index -= 1; + } return true; } @@ -1736,8 +1857,12 @@ bool Generator::CallVariable(Item::Function & item_fun, Var & variab } else { - out_stream << variable.str; - last_res = variable.res; + if( !IsTestingFunctionExistence() ) + { + out_stream << variable.str; + last_res = variable.res; + } + return true; } } @@ -1793,7 +1918,7 @@ std::vector parameters; #ifdef EZC_HAS_MORM_LIBRARY if( find_helper.wrapper ) - CallWrapper(find_helper, item_fun.fields, parameters, out_stream, in_stream); + return CallWrapper(find_helper, item_fun.fields, parameters, out_stream, in_stream); else #endif if( find_helper.base_obj ) @@ -2250,6 +2375,42 @@ void Generator::MakeTextIf(Item & item) } +template +void Generator::MakeTextIfDef(Item & item) +{ + is_generating_if_def = true; + + if( program_mode ) + { + //CHECKME + //EvaluateProgramNode(item); + } + else + { + last_res = Call(item.function); + } + + MakeTextIf_go(item, last_res); +} + + +template +void Generator::MakeTextIfNotDef(Item & item) +{ + is_generating_if_not_def = true; + + if( program_mode ) + { + //CHECKME + //EvaluateProgramNode(item); + } + else + { + last_res = !Call(item.function); + } + + MakeTextIf_go(item, last_res); +} template @@ -2598,12 +2759,14 @@ void Generator::MakeText(Item & item) if( LimitAchieved() ) return; - current_item += 1; - stack_index += 1; - is_generating_for = false; - is_generating_if = false; - is_generating_normal = false; - is_generating_filter = false; + current_item += 1; + stack_index += 1; + is_generating_for = false; + is_generating_if = false; + is_generating_if_def = false; + is_generating_if_not_def = false; + is_generating_normal = false; + is_generating_filter = false; stack_tab[stack_index-1].Clear(); stack_tab[stack_index-1].item = &item; @@ -2612,6 +2775,8 @@ void Generator::MakeText(Item & item) else if( item.type == Item::item_container ) MakeTextContainer(item); else if( item.type == Item::item_function ) MakeTextFunction(item); else if( item.type == Item::item_if ) MakeTextIf(item); + else if( item.type == Item::item_if_def ) MakeTextIfDef(item); + else if( item.type == Item::item_if_not_def ) MakeTextIfNotDef(item); else if( item.type == Item::item_def ) MakeTextDefine(item); else if( item.type == Item::item_def_if_not_set ) MakeTextDefineIfNotSet(item); else if( item.type == Item::item_let ) MakeTextLet(item); diff --git a/src/item.h b/src/item.h index 3e5ce13..f69bf05 100644 --- a/src/item.h +++ b/src/item.h @@ -53,7 +53,7 @@ struct Item { enum Type { - item_none, item_container, item_text, item_function, item_if, + item_none, item_container, item_text, item_function, item_if, item_if_def, item_if_not_def, item_for, item_else, item_end, item_err, item_include, item_comment, item_def, item_def_if_not_set, item_let, item_let_if_not_set, item_filter, item_ezc, item_block, item_return diff --git a/src/patternparser.cpp b/src/patternparser.cpp index 7402133..0ac1478 100644 --- a/src/patternparser.cpp +++ b/src/patternparser.cpp @@ -745,6 +745,35 @@ void PatternParser::ReadDirectiveIf(Item & item) } +void PatternParser::ReadDirectiveIfDef(Item & item) +{ + item.type = Item::item_if_def; + + if( ReadFunction(item) ) + { + if( !item.function.is_function || item.function.parameters.size() > 0 ) + { + item.type = Item::item_err; + item.function.Clear(); + } + } +} + + +void PatternParser::ReadDirectiveIfNotDef(Item & item) +{ + item.type = Item::item_if_not_def; + + if( ReadFunction(item) ) + { + if( !item.function.is_function || item.function.parameters.size() > 0 ) + { + item.type = Item::item_err; + item.function.Clear(); + } + } +} + void PatternParser::ReadDirectiveEnd(Item & item) { @@ -991,6 +1020,8 @@ std::wstring name; ReadName(name); if ( name == L"if" ) ReadDirectiveIf(item); + else if( name == L"if-def" ) ReadDirectiveIfDef(item); + else if( name == L"if-not-def" )ReadDirectiveIfNotDef(item); else if( name == L"end" ) ReadDirectiveEnd(item); else if( name == L"else" ) ReadDirectiveElse(item); else if( name == L"for" ) ReadDirectiveFor(item); @@ -1325,7 +1356,7 @@ bool PatternParser::CreateTree(Item & item) if( item.type == Item::item_container ) CreateTreeContainer(item); - if( item.type == Item::item_if ) + if( item.type == Item::item_if || item.type == Item::item_if_def || item.type == Item::item_if_not_def ) CreateTreeReadIf(item); // reads one child or two if [else] statement is present if( item.type == Item::item_for || diff --git a/src/patternparser.h b/src/patternparser.h index 421d1ad..3e755cc 100644 --- a/src/patternparser.h +++ b/src/patternparser.h @@ -176,6 +176,8 @@ private: bool ReadFunction(Item & item); void ReadDirectiveIf(Item & item); + void ReadDirectiveIfDef(Item & item); + void ReadDirectiveIfNotDef(Item & item); void ReadDirectiveEnd(Item & item); void ReadDirectiveElse(Item & item); void ReadDirectiveFor(Item & item); From b9b9a881e05f5cff58e23887546acceb9d154ec5 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Tue, 6 Jul 2021 21:47:42 +0200 Subject: [PATCH 19/19] added "roman" and "no_sec" parameters when serializing a date --- src/generator.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/generator.h b/src/generator.h index a34664d..6c71d3d 100644 --- a/src/generator.h +++ b/src/generator.h @@ -1305,10 +1305,10 @@ void Generator::DumpModelIfNeeded(morm::Model & model, std::vector void Generator::PrintDate(pt::Date * date, std::vector parameters, StreamType & out_stream) { - // IMPROVEME - // check for different formats depending on parameters + bool is_roman = HasParam(parameters, L"roman"); + bool is_no_sec = HasParam(parameters, L"no_sec"); - date->Serialize(out_stream); + date->Serialize(out_stream, is_roman, !is_no_sec); } @@ -1326,7 +1326,14 @@ bool Generator::PrintDatePart(pt::Date * date, const std::wstring & if( field == L"month" ) { if( !is_test ) - out_stream << date->month; + { + bool is_roman = HasParam(parameters, L"roman"); + + if( is_roman ) + pt::Date::SerializeMonthAsRoman(out_stream, date->month); + else + out_stream << date->month; + } } else if( field == L"day" )