2010-11-22 02:23:32 +01:00
/*
2014-10-17 23:48:11 +02:00
* This file is a part of EZC - - Easy templating in C + + library
* and is distributed under the BSD 3 - Clause licence .
2010-11-22 02:23:32 +01:00
* Author : Tomasz Sowa < t . sowa @ ttmath . org >
*/
/*
2021-05-23 10:02:51 +02:00
* Copyright ( c ) 2007 - 2021 , Tomasz Sowa
2010-11-22 02:23:32 +01:00
* 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_generator
# define headerfile_ezc_generator
2021-05-31 18:37:09 +02:00
# include <sstream>
# include <fstream>
# include <vector>
2014-10-17 23:36:55 +02:00
# include "blocks.h"
2010-11-22 02:23:32 +01:00
# include "pattern.h"
# include "functions.h"
2015-06-14 20:20:00 +02:00
# include "objects.h"
2015-11-12 10:53:20 +01:00
# include "outstreams.h"
2018-10-30 00:50:10 +01:00
# include "expressionparser.h"
2021-05-31 18:37:09 +02:00
# include "models.h"
2021-06-19 20:18:30 +02:00
# include "log/log.h"
2021-06-20 16:54:55 +02:00
# include "utf8/utf8.h"
2011-01-26 13:42:49 +01:00
2021-06-16 14:16:49 +02:00
# ifdef EZC_HAS_MORM_LIBRARY
# include "model.h"
# endif
2010-11-22 02:23:32 +01:00
namespace Ezc
{
2012-02-27 18:39:46 +01:00
2010-11-25 02:55:32 +01:00
/*
StreamType
2010-11-25 23:39:58 +01:00
we use only method write ( const wchar_t * str , size_t len ) from the stream
2010-11-25 02:55:32 +01:00
*/
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream = false , bool is_autoescape_stream = false >
2010-11-22 02:23:32 +01:00
class Generator
{
public :
Generator ( ) ;
2011-01-26 13:42:49 +01:00
Generator ( const Generator & n ) ;
Generator & operator = ( const Generator & n ) ;
~ Generator ( ) ;
2014-10-17 23:36:55 +02:00
void SetPattern ( Pattern & pattern ) ;
void SetBlocks ( Blocks & blocks ) ;
void SetFunctions ( Functions < StreamType > & functions ) ;
2015-06-14 20:20:00 +02:00
void SetObjects ( Objects < StreamType > & objects ) ;
2021-05-23 10:02:51 +02:00
void SetVariables ( Vars & variables ) ; // [def] and [let]
2021-06-16 14:16:49 +02:00
2021-06-19 20:18:30 +02:00
void SetLogger ( pt : : Log & logger ) ;
2021-06-16 14:16:49 +02:00
# ifdef EZC_HAS_MORM_LIBRARY
2021-05-31 18:37:09 +02:00
void SetModels ( Models & models ) ;
2021-06-16 14:16:49 +02:00
# endif
2010-11-22 02:23:32 +01:00
2012-02-24 13:04:36 +01:00
void SetMax ( size_t max_items_ , size_t max_for_items_ ) ;
2010-11-22 02:23:32 +01:00
// recognizing some special characters in text patterns (item_text in Patterns)
// \r will be a carriage return (13)
// \n will be a new line (10)
// \t will be a tabulator (9)
// \s will be a space
// \\ will be one '\'
2010-11-25 02:55:32 +01:00
// if the second character is different from those shown above the first slash will be printed
// so "\x" gives "\x"
2010-11-22 02:23:32 +01:00
// default: false
void RecognizeSpecialChars ( bool spec ) ;
// trimming white characters (at the beginning and at the end of an item_text)
// (special char \s if enabled is not treated as a white character here)
// default: false
void TrimWhite ( bool trim ) ;
// skipping new line characters (from the whole string in an item_text)
// but you can use a new line character written as "\n" (if special chars are turn on)
// default: false
void SkipNewLine ( bool skip ) ;
2011-01-26 13:42:49 +01:00
// default: 20
void SetMaxFilters ( size_t new_len ) ;
2012-02-27 18:39:46 +01:00
// default stack size: 300
void SetStackSize ( size_t new_stack_size ) ;
2014-10-19 23:09:34 +02:00
// set whether or not we can use cache for functions or blocks
// true by default
void CanUseCache ( bool can_use_cache ) ;
// set whether or not we can use variables: [def ...] statement
// true by default
void CanUseVars ( bool can_use_variables ) ;
2018-10-30 00:50:10 +01:00
void SetProgramMode ( bool program_mode ) ;
void SetExpressionParser ( ExpressionParser * expression_parser ) ;
2010-11-25 23:39:58 +01:00
// the main methods for generating
2015-11-12 10:53:20 +01:00
void Generate ( StreamType & out ) ;
2021-07-12 23:00:11 +02:00
void Generate ( StreamType & out , OutStreams < StreamType , is_pikotools_stream > & out_streams ) ;
void Generate ( OutStreams < StreamType , is_pikotools_stream > & out_streams ) ;
2015-11-12 10:53:20 +01:00
2010-11-25 23:39:58 +01:00
2010-11-22 02:23:32 +01:00
private :
2014-10-28 18:46:24 +01:00
2021-06-16 14:16:49 +02:00
struct FindHelper
{
2021-06-19 20:18:30 +02:00
std : : wstring * fun_name ;
2021-06-16 14:16:49 +02:00
BaseObj < StreamType > * base_obj ;
int method_index ;
typename Functions < StreamType > : : UserFunction * function ;
Item * item_block ;
Var * variable ;
2021-06-19 20:18:30 +02:00
# ifdef EZC_HAS_MORM_LIBRARY
2021-07-01 23:21:20 +02:00
morm : : Wrapper * wrapper ;
size_t field_index ;
2021-06-19 20:18:30 +02:00
# endif
2021-06-16 14:16:49 +02:00
FindHelper ( )
{
2021-06-19 20:18:30 +02:00
fun_name = nullptr ;
2021-06-16 14:16:49 +02:00
base_obj = nullptr ;
method_index = - 1 ;
function = nullptr ;
item_block = nullptr ;
variable = nullptr ;
2021-06-19 20:18:30 +02:00
2021-06-16 14:16:49 +02:00
# ifdef EZC_HAS_MORM_LIBRARY
2021-07-01 23:21:20 +02:00
wrapper = nullptr ;
2021-06-16 14:16:49 +02:00
field_index = 0 ;
2021-07-01 23:21:20 +02:00
# endif
2021-06-16 14:16:49 +02:00
}
} ;
2014-10-17 23:36:55 +02:00
struct BlockStack
{
2014-10-28 18:46:24 +01:00
std : : vector < Var > args ;
2014-10-17 23:36:55 +02:00
StreamType * out_stream ;
2014-10-28 18:46:24 +01:00
bool was_return ;
2014-10-17 23:36:55 +02:00
} ;
std : : vector < BlockStack > block_stack_tab ;
size_t block_stack_index ;
size_t block_stack_size ;
2015-11-12 10:53:20 +01:00
// current output stream (can be null)
// at the beginning it is pointing to the main stream (to the StreamType argument passsed to Generate method)
2010-11-22 02:23:32 +01:00
StreamType * output_stream ;
2014-10-17 23:36:55 +02:00
Pattern * ppattern ;
Blocks * pblocks ;
Functions < StreamType > * pfunctions ;
2015-06-14 20:20:00 +02:00
Objects < StreamType > * pobjects ;
2021-06-16 14:16:49 +02:00
# ifdef EZC_HAS_MORM_LIBRARY
2021-05-31 18:37:09 +02:00
Models * pmodels ;
2021-06-16 14:16:49 +02:00
# endif
2021-06-19 20:18:30 +02:00
Vars * pvars ;
pt : : Log * plog ;
2013-11-07 11:16:10 +01:00
2015-11-12 10:53:20 +01:00
// pointer to the output streams map (can be null)
2021-05-28 16:10:16 +02:00
// output stream will be created when [ezc frame "stream_name"] statement is found
2021-07-12 23:00:11 +02:00
OutStreams < StreamType , is_pikotools_stream > * output_frames_streams ;
2013-11-07 11:16:10 +01:00
2010-11-22 02:23:32 +01:00
// temporary error messages
std : : wstring temp_msg ;
bool break_generating ;
2012-02-24 13:04:36 +01:00
size_t current_item ;
size_t max_items ;
size_t max_for_items ;
2010-11-22 02:23:32 +01:00
bool special_chars ;
bool trim_white ;
bool skip_new_line ;
2012-02-27 18:39:46 +01:00
2021-05-28 16:10:16 +02:00
size_t ezc_frames_stack_index ;
size_t ezc_frames_stack_size ;
2015-11-12 10:53:20 +01:00
2012-02-27 18:39:46 +01:00
size_t stack_index ;
size_t stack_size ;
2011-01-26 13:42:49 +01:00
size_t filter_index ;
size_t filter_size ;
// we have to use a pointers table because standard streams such
// as std::wostringstream are not copyable
std : : vector < StreamType * > filter_tab ;
2021-05-28 16:10:16 +02:00
std : : vector < StreamType * > ezc_frame_stack_tab ;
2011-01-26 13:42:49 +01:00
const StreamType empty_stream ;
2014-11-02 18:26:56 +01:00
// temporary streams used in [if..] [for...] or [def ...]
2013-11-07 11:16:10 +01:00
// or if output_stream is null and an ezc function should be called
2014-11-02 18:26:56 +01:00
StreamType stream_temp1 , stream_temp_define ;
2011-01-26 13:42:49 +01:00
2011-04-26 19:17:06 +02:00
// last result from a user function (FunInfo::res)
bool last_res ;
2010-11-22 02:23:32 +01:00
2011-04-26 19:17:06 +02:00
// true if this Generator is working now
bool is_generator_working ;
2012-02-24 13:04:36 +01:00
// true if the Generator is working with [for ...], [if ...] etc.
2012-01-17 23:57:06 +01:00
bool is_generating_for ;
2012-02-24 13:04:36 +01:00
bool is_generating_if ;
2021-07-02 20:23:20 +02:00
bool is_generating_if_def ;
bool is_generating_if_not_def ;
2012-02-24 13:04:36 +01:00
bool is_generating_normal ;
bool is_generating_filter ;
2012-01-17 23:57:06 +01:00
2011-04-26 19:17:06 +02:00
// an empty string for FunInfo objects
2010-11-22 02:23:32 +01:00
// when there is no any parameters
const std : : wstring empty ;
2011-04-26 19:17:06 +02:00
// a stack for [for] statements
2012-02-27 18:39:46 +01:00
std : : vector < Stack > stack_tab ;
2011-01-15 00:59:30 +01:00
2014-10-19 23:09:34 +02:00
bool can_use_vars ;
bool can_find_in_cache ;
2018-10-30 00:50:10 +01:00
bool program_mode ;
ExpressionParser * expression_parser ;
2015-11-12 10:53:20 +01:00
void ResizeStreamStack ( std : : vector < StreamType * > & stream_tab , size_t stream_tab_max_size ) ;
2011-01-26 13:42:49 +01:00
void ResizeFilterTab ( ) ;
2012-02-27 18:39:46 +01:00
void ResizeStack ( ) ;
2014-10-17 23:36:55 +02:00
void ResizeBlockStack ( ) ;
2021-05-28 16:10:16 +02:00
void ResizeEzcFrameStack ( ) ;
2014-10-17 23:36:55 +02:00
2015-11-12 10:53:20 +01:00
void ClearStreamStack ( std : : vector < StreamType * > & stream_tab ) ;
2011-01-26 13:42:49 +01:00
void ClearFilterTab ( ) ;
2014-10-17 23:36:55 +02:00
void ClearForStack ( ) ;
2014-10-21 09:21:20 +02:00
void ClearBlockStack ( ) ;
2021-05-28 16:10:16 +02:00
void ClearEzcFrameTab ( ) ;
2014-10-21 09:21:20 +02:00
2011-01-26 13:42:49 +01:00
void ClearStream ( StreamType & str ) ;
2021-06-20 16:54:55 +02:00
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 ) ;
2012-02-27 18:39:46 +01:00
void RemoveStackFunData ( Stack & sitem ) ;
2011-01-26 13:42:49 +01:00
2015-03-08 03:31:21 +01:00
bool ConvertToBool ( const std : : wstring & str ) ;
2011-04-26 19:17:06 +02:00
template < class CharType >
CharType ToLower ( CharType c ) ;
2021-07-02 20:23:20 +02:00
bool IsTestingFunctionExistence ( ) ;
2015-06-14 20:20:00 +02:00
2021-06-16 14:16:49 +02:00
bool CheckBlockArgument ( int arg_index , FindHelper & find_helper ) ;
2015-06-14 20:20:00 +02:00
2021-06-16 14:16:49 +02:00
bool FindInCache ( Item : : Function & item_fun , FindHelper & find_helper ) ;
2011-04-26 19:17:06 +02:00
2021-06-16 14:16:49 +02:00
# ifdef EZC_HAS_MORM_LIBRARY
2021-06-19 20:18:30 +02:00
bool FindInModels ( FindHelper & find_helper ) ;
2021-06-16 14:16:49 +02:00
# endif
2021-05-31 18:37:09 +02:00
2021-06-16 14:16:49 +02:00
bool FindInFunctionsAndBlocks ( const std : : wstring & name , FindHelper & find_helper ) ;
bool FindInVariables ( const std : : wstring & name , FindHelper & find_helper ) ;
2021-06-19 20:18:30 +02:00
bool Find ( Item : : Function & item_fun , FindHelper & find_helper ) ;
2011-01-26 13:42:49 +01:00
2021-07-02 20:23:20 +02:00
void PrepareEnvStruct ( FunInfo < StreamType > & info ) ;
2021-06-16 14:16:49 +02:00
void CallFunction ( typename Functions < StreamType > : : UserFunction & function , FunInfo < StreamType > & info ) ;
2014-10-17 23:36:55 +02:00
2021-06-16 14:16:49 +02:00
void CallFunction ( typename Functions < StreamType > : : UserFunction & function ,
2014-10-28 18:46:24 +01:00
std : : vector < Var > & parameters ,
StreamType & out_stream ,
const StreamType & in_stream ) ;
2014-10-17 23:36:55 +02:00
bool CallBlock ( Item & item_block ,
2014-10-28 18:46:24 +01:00
std : : vector < Var > & parameters ,
2014-10-17 23:36:55 +02:00
StreamType & out_stream ) ;
2021-06-16 14:16:49 +02:00
void CallObject ( BaseObj < StreamType > & base_obj , int method_index , FunInfo < StreamType > & info ) ;
2015-06-14 20:20:00 +02:00
2021-07-01 23:21:20 +02:00
void PrintDate ( pt : : Date * date , std : : vector < Var > parameters , StreamType & out_stream ) ;
bool PrintDatePart ( pt : : Date * date , const std : : wstring & field , std : : vector < Var > parameters , StreamType & out_stream ) ;
2021-07-02 20:23:20 +02:00
bool CallDate ( FindHelper & find_helper , std : : vector < std : : wstring > & fields , std : : vector < Var > parameters , StreamType & out_stream ) ;
2021-06-25 16:16:30 +02:00
2021-07-02 20:23:20 +02:00
void PrintLastSpaceField ( pt : : Space * space , std : : vector < Var > & parameters , StreamType & out_stream ) ;
void CallSpaceObjectForLastField ( std : : vector < Var > & parameters , StreamType & out_stream , pt : : Space * space ) ;
2021-06-25 16:16:30 +02:00
pt : : Space * CallSpaceObjectForMiddleField ( std : : wstring & root_space_name , std : : vector < std : : wstring > & fields , size_t field_index , pt : : Space * space ) ;
2021-07-01 23:21:20 +02:00
void CallSpaceTableForLastField ( morm : : SpaceWrapper & space_wrapper , std : : vector < Var > & parameters , StreamType & out_stream ,
2021-06-25 16:16:30 +02:00
pt : : Space * space , size_t model_wrapper_space_table_index ) ;
2021-07-01 23:21:20 +02:00
pt : : Space * CallSpaceTableForMiddleField ( morm : : SpaceWrapper & space_wrapper , std : : wstring & root_space_name , std : : vector < std : : wstring > & fields ,
2021-06-25 16:16:30 +02:00
size_t field_index , pt : : Space * space , size_t model_wrapper_space_table_index ) ;
2021-07-02 20:23:20 +02:00
bool CallSpace ( FindHelper & find_helper , std : : vector < std : : wstring > & fields , std : : vector < Var > & parameters , StreamType & out_stream ) ;
2021-06-22 18:01:47 +02:00
2021-06-16 14:16:49 +02:00
# ifdef EZC_HAS_MORM_LIBRARY
2021-07-01 23:21:20 +02:00
bool CallModelField ( morm : : Model & model , const std : : wstring & field , std : : vector < Var > parameters , StreamType & out_stream , const StreamType & in_stream ) ;
2021-07-02 20:23:20 +02:00
bool CallModel ( morm : : Model & model , FindHelper & find_helper , std : : vector < std : : wstring > & fields , std : : vector < Var > parameters , StreamType & out_stream , const StreamType & in_stream ) ;
2021-07-01 23:21:20 +02:00
void FindLastModelWrapper ( FindHelper & find_helper , std : : vector < std : : wstring > & fields ) ;
2021-07-02 20:23:20 +02:00
bool CallWrapper ( FindHelper & find_helper , std : : vector < std : : wstring > & fields , std : : vector < Var > parameters , StreamType & out_stream , const StreamType & in_stream ) ;
2021-06-16 14:16:49 +02:00
# endif
2015-06-14 20:20:00 +02:00
2021-06-16 14:16:49 +02:00
void CallObject ( BaseObj < StreamType > & base_obj ,
2015-06-14 20:20:00 +02:00
int method_index ,
std : : vector < Var > & parameters ,
StreamType & out_stream ,
const StreamType & in_stream ) ;
2021-05-23 10:02:51 +02:00
bool CallVariable ( Item : : Function & item_fun ,
2021-06-16 14:16:49 +02:00
Var & variable ,
2021-05-23 10:02:51 +02:00
std : : vector < Var > & parameters ,
StreamType & out_stream ,
const StreamType & in_stream ) ;
2015-06-14 20:20:00 +02:00
2014-10-17 23:36:55 +02:00
bool Call ( Item : : Function & item_fun ,
2021-05-23 10:02:51 +02:00
std : : wstring * fun_name ,
2014-10-17 23:36:55 +02:00
StreamType & out_stream ,
bool clear_out_stream ,
const StreamType & in_stream ) ;
bool Call ( Item : : Function & item_fun ) ;
2011-01-26 13:42:49 +01:00
2010-11-22 02:23:32 +01:00
wchar_t CreateSpecialChar ( wchar_t c ) ;
2010-11-25 02:55:32 +01:00
const wchar_t * PrintSpecialChar ( const wchar_t * start , const wchar_t * end ) ;
2010-11-22 02:23:32 +01:00
void PrintSpecialText ( const wchar_t * start , const wchar_t * end ) ;
void PrintNormalText ( const wchar_t * start , const wchar_t * end ) ;
2014-10-11 21:56:48 +02:00
bool IsWhite ( wchar_t c ) ;
2010-11-22 02:23:32 +01:00
void TrimWhite ( const wchar_t * & start , const wchar_t * & end ) ;
void SkipWhite ( const wchar_t * & str ) ;
2013-11-07 11:16:10 +01:00
size_t StrToSize ( const wchar_t * str , const wchar_t * * str_end = 0 ) ;
2021-06-27 22:42:00 +02:00
bool HasParam ( std : : vector < Var > & parameters , const wchar_t * param1 , const wchar_t * param2 = nullptr ) ;
bool ShouldMakeSpaceDump ( std : : vector < Var > & parameters ) ;
bool ShouldMakeJsonDump ( std : : vector < Var > & parameters ) ;
bool IsPrettyPrint ( std : : vector < Var > & parameters ) ;
2021-06-22 18:01:47 +02:00
bool IsCurrentParam ( std : : vector < Var > & parameters ) ;
2021-06-27 22:42:00 +02:00
void DumpSpaceIfNeeded ( std : : vector < Var > & parameters , StreamType & out_stream , pt : : Space * space ) ;
2021-07-01 23:21:20 +02:00
void DumpModelIfNeeded ( morm : : Model & model , std : : vector < Var > & parameters , StreamType & out_stream ) ;
2010-11-22 02:23:32 +01:00
2013-11-07 11:16:10 +01:00
2015-11-12 10:53:20 +01:00
void CopyTmpStreamToOutputStreams ( Item : : Function & fun , StreamType & ezc_out_tmp_stream , StreamType & previous_stream ) ;
2021-06-19 20:18:30 +02:00
2021-06-25 16:16:30 +02:00
void CreateMsg ( const wchar_t * type , const std : : wstring & model_name , std : : vector < std : : wstring > & fields , size_t how_many_fields_print ,
const wchar_t * arg = nullptr , const wchar_t * arg2 = nullptr , const wchar_t * arg3 = nullptr ) ;
2021-06-19 20:18:30 +02:00
void CreateMsg ( const wchar_t * type , const std : : wstring & model_name , std : : vector < std : : wstring > & 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 ) ;
2010-11-25 23:39:58 +01:00
void CreateMsg ( const std : : wstring & type , const std : : wstring & arg ) ;
void CreateMsg ( const std : : wstring & type ) ;
2021-06-19 20:18:30 +02:00
2012-02-27 18:39:46 +01:00
bool LimitAchieved ( ) ;
2010-11-22 02:23:32 +01:00
2018-10-30 00:50:10 +01:00
void EvaluateProgramNode ( Item & item ) ;
2010-11-22 02:23:32 +01:00
void MakeTextIf_go ( Item & item , bool result ) ;
void MakeTextIf ( Item & item ) ;
2021-07-02 20:23:20 +02:00
void MakeTextIfDef ( Item & item ) ;
void MakeTextIfNotDef ( Item & item ) ;
2010-11-22 02:23:32 +01:00
void MakeTextFor ( Item & item ) ;
void MakeItemText ( Item & item ) ;
void MakeTextContainer ( Item & item ) ;
2021-06-20 16:54:55 +02:00
void MakeTextFunction ( Item & item ) ;
2021-05-23 10:02:51 +02:00
void MakeTextDefine ( Item & item , Var & var ) ;
2010-11-22 02:23:32 +01:00
void MakeTextDefine ( Item & item ) ;
2021-05-23 10:02:51 +02:00
void MakeTextDefineIfNotSet ( Item & item ) ;
void MakeTextLet ( Item & item , Var & var ) ;
void MakeTextLet ( Item & item ) ;
void MakeTextLetIfNotSet ( Item & item ) ;
2011-01-26 13:42:49 +01:00
void MakeTextFilter ( Item & item ) ;
2013-11-07 11:16:10 +01:00
void MakeTextEzc ( Item & item ) ;
2014-10-28 18:46:24 +01:00
void MakeTextReturn ( Item & item ) ;
2010-11-22 02:23:32 +01:00
void MakeText ( Item & item ) ;
2021-05-28 16:10:16 +02:00
void MakeEzcFrame ( Item & item ) ;
2013-11-07 11:16:10 +01:00
2014-10-17 23:36:55 +02:00
void Generate ( ) ;
2013-11-07 11:16:10 +01:00
2011-01-26 13:42:49 +01:00
2010-11-22 02:23:32 +01:00
} ; // class Generator
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : Generator ( ) : empty_stream ( )
2010-11-22 02:23:32 +01:00
{
2021-05-31 18:37:09 +02:00
ppattern = nullptr ;
pblocks = nullptr ;
pfunctions = nullptr ;
pobjects = nullptr ;
pvars = nullptr ;
2021-06-19 20:18:30 +02:00
plog = nullptr ;
2021-06-16 14:16:49 +02:00
# ifdef EZC_HAS_MORM_LIBRARY
2021-05-31 18:37:09 +02:00
pmodels = nullptr ;
2021-06-16 14:16:49 +02:00
# endif
2010-11-22 02:23:32 +01:00
max_items = 50000 ;
max_for_items = 5000 ;
2011-01-26 13:42:49 +01:00
filter_size = 20 ;
2010-11-22 02:23:32 +01:00
special_chars = false ;
trim_white = false ;
skip_new_line = false ;
2011-04-26 19:17:06 +02:00
is_generator_working = false ;
2012-02-27 18:39:46 +01:00
stack_size = 300 ;
2014-10-17 23:36:55 +02:00
block_stack_size = 64 ;
2021-05-28 16:10:16 +02:00
ezc_frames_stack_size = 16 ;
2014-10-19 23:09:34 +02:00
can_find_in_cache = true ;
can_use_vars = true ;
2018-10-30 00:50:10 +01:00
expression_parser = nullptr ;
2018-11-01 22:52:33 +01:00
program_mode = false ;
2010-11-22 02:23:32 +01:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : Generator ( const Generator < StreamType , is_pikotools_stream , is_autoescape_stream > & n )
2011-01-26 13:42:49 +01:00
{
operator = ( n ) ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
Generator < StreamType , is_pikotools_stream , is_autoescape_stream > &
Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : operator = ( const Generator < StreamType , is_pikotools_stream , is_autoescape_stream > & n )
2011-01-26 13:42:49 +01:00
{
2014-10-17 23:36:55 +02:00
ppattern = n . ppattern ;
pblocks = n . pblocks ;
pfunctions = n . pfunctions ;
2015-06-14 20:20:00 +02:00
pobjects = n . pobjects ;
2021-05-23 10:02:51 +02:00
pvars = n . pvars ;
2021-06-19 20:18:30 +02:00
plog = n . plog ;
2021-06-16 14:16:49 +02:00
# ifdef EZC_HAS_MORM_LIBRARY
2021-05-31 18:37:09 +02:00
pmodels = n . pmodels ;
2021-06-16 14:16:49 +02:00
# endif
2014-10-17 23:36:55 +02:00
2012-02-27 18:39:46 +01:00
max_items = n . max_items ;
max_for_items = n . max_for_items ;
special_chars = n . special_chars ;
trim_white = n . trim_white ;
skip_new_line = n . skip_new_line ;
2014-10-19 23:09:34 +02:00
can_find_in_cache = n . can_find_in_cache ;
can_use_vars = n . can_use_vars ;
2012-02-27 18:39:46 +01:00
2014-10-17 23:36:55 +02:00
// filter, stack and block_stack will be auto resized when calling Generate() method
filter_size = n . filter_size ;
stack_size = n . stack_size ;
block_stack_size = n . block_stack_size ;
2021-05-28 16:10:16 +02:00
ezc_frames_stack_size = n . ezc_frames_stack_size ;
2018-10-30 00:50:10 +01:00
expression_parser = n . expression_parser ;
2018-11-01 22:52:33 +01:00
program_mode = n . program_mode ;
2014-10-17 23:36:55 +02:00
2014-10-19 23:09:34 +02:00
// vars doesn't have to be copied
2012-02-27 18:39:46 +01:00
2011-01-26 13:42:49 +01:00
// don't copy filter tab
2012-02-27 18:39:46 +01:00
// don't copy stack
2021-05-28 16:10:16 +02:00
// don't copy ezc_frame_stack_tab
// don't copy output_stream and output_frames_streams
2011-01-26 13:42:49 +01:00
2012-02-25 04:29:44 +01:00
// !! CHECK ME
// may copying should be denied when generator is working?
2011-04-26 19:17:06 +02:00
// don't copy 'is_generator_working' flag
is_generator_working = false ;
2011-01-26 13:42:49 +01:00
return * this ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : ~ Generator ( )
2011-01-26 13:42:49 +01:00
{
ClearFilterTab ( ) ;
2012-02-24 13:04:36 +01:00
ClearForStack ( ) ;
2014-10-21 09:21:20 +02:00
ClearBlockStack ( ) ;
2021-05-28 16:10:16 +02:00
ClearEzcFrameTab ( ) ;
2011-01-26 13:42:49 +01:00
}
2014-10-19 07:42:25 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : SetPattern ( Pattern & pattern )
2014-10-17 23:36:55 +02:00
{
ppattern = & pattern ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : SetBlocks ( Blocks & blocks )
2014-10-17 23:36:55 +02:00
{
pblocks = & blocks ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : SetFunctions ( Functions < StreamType > & functions )
2014-10-17 23:36:55 +02:00
{
pfunctions = & functions ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : SetObjects ( Objects < StreamType > & objects )
2015-06-14 20:20:00 +02:00
{
pobjects = & objects ;
}
2021-05-23 10:02:51 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : SetVariables ( Vars & variables )
2021-05-23 10:02:51 +02:00
{
pvars = & variables ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : SetLogger ( pt : : Log & logger )
2021-06-19 20:18:30 +02:00
{
plog = & logger ;
}
2021-06-16 14:16:49 +02:00
# ifdef EZC_HAS_MORM_LIBRARY
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : SetModels ( Models & models )
2021-05-31 18:37:09 +02:00
{
pmodels = & models ;
}
2021-06-16 14:16:49 +02:00
# endif
2021-05-31 18:37:09 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CanUseCache ( bool can_use_cache )
2014-10-19 23:09:34 +02:00
{
can_find_in_cache = can_use_cache ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CanUseVars ( bool can_use_variables )
2014-10-19 23:09:34 +02:00
{
can_use_vars = can_use_variables ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : SetProgramMode ( bool set_program_mode )
2018-10-30 00:50:10 +01:00
{
this - > program_mode = set_program_mode ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : SetExpressionParser ( ExpressionParser * expression_parser )
2018-10-30 00:50:10 +01:00
{
this - > expression_parser = expression_parser ;
}
2014-10-19 23:09:34 +02:00
2014-10-17 23:36:55 +02:00
2015-11-12 10:53:20 +01:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : ResizeStack ( )
2011-01-26 13:42:49 +01:00
{
2015-11-12 10:53:20 +01:00
if ( stack_tab . size ( ) ! = stack_size )
2011-01-26 13:42:49 +01:00
{
2015-11-12 10:53:20 +01:00
if ( stack_tab . size ( ) > stack_size )
2011-01-26 13:42:49 +01:00
{
2015-11-12 10:53:20 +01:00
for ( size_t i = stack_size ; i < stack_tab . size ( ) ; + + i )
RemoveStackFunData ( stack_tab [ i ] ) ;
}
stack_tab . resize ( stack_size ) ;
}
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : ResizeStreamStack ( std : : vector < StreamType * > & stream_tab , size_t stream_tab_max_size )
2015-11-12 10:53:20 +01:00
{
if ( stream_tab . size ( ) ! = stream_tab_max_size )
{
if ( stream_tab . size ( ) < stream_tab_max_size )
{
size_t i = stream_tab . size ( ) ;
stream_tab . resize ( stream_tab_max_size ) ;
for ( ; i < stream_tab . size ( ) ; + + i )
stream_tab [ i ] = new StreamType ( ) ;
2011-01-26 13:42:49 +01:00
}
else
{
2015-11-12 10:53:20 +01:00
for ( size_t i = stream_tab_max_size ; i < stream_tab . size ( ) ; + + i )
delete stream_tab [ i ] ;
2011-01-26 13:42:49 +01:00
2015-11-12 10:53:20 +01:00
stream_tab . resize ( stream_tab_max_size ) ;
2011-01-26 13:42:49 +01:00
}
}
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : ResizeFilterTab ( )
2012-02-27 18:39:46 +01:00
{
2015-11-12 10:53:20 +01:00
ResizeStreamStack ( filter_tab , filter_size ) ;
}
2012-02-27 18:39:46 +01:00
2015-11-12 10:53:20 +01:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : ResizeEzcFrameStack ( )
2015-11-12 10:53:20 +01:00
{
2021-05-28 16:10:16 +02:00
ResizeStreamStack ( ezc_frame_stack_tab , ezc_frames_stack_size ) ;
2012-02-27 18:39:46 +01:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : ResizeBlockStack ( )
2014-10-17 23:36:55 +02:00
{
if ( block_stack_tab . size ( ) ! = block_stack_size )
{
if ( block_stack_tab . size ( ) < block_stack_size )
{
size_t i = block_stack_tab . size ( ) ;
block_stack_tab . resize ( block_stack_size ) ;
for ( ; i < block_stack_tab . size ( ) ; + + i )
block_stack_tab [ i ] . out_stream = new StreamType ( ) ;
}
else
{
for ( size_t i = block_stack_size ; i < block_stack_tab . size ( ) ; + + i )
delete block_stack_tab [ i ] . out_stream ;
block_stack_tab . resize ( block_stack_size ) ;
}
}
}
2015-11-12 10:53:20 +01:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : ClearStreamStack ( std : : vector < StreamType * > & stream_tab )
2015-11-12 10:53:20 +01:00
{
for ( size_t i = 0 ; i < stream_tab . size ( ) ; + + i )
delete stream_tab [ i ] ;
stream_tab . clear ( ) ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : ClearFilterTab ( )
2011-01-26 13:42:49 +01:00
{
2015-11-12 10:53:20 +01:00
ClearStreamStack ( filter_tab ) ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : ClearEzcFrameTab ( )
2015-11-12 10:53:20 +01:00
{
2021-05-28 16:10:16 +02:00
ClearStreamStack ( ezc_frame_stack_tab ) ;
2011-01-26 13:42:49 +01:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : ClearBlockStack ( )
2014-10-21 09:21:20 +02:00
{
for ( size_t i = 0 ; i < block_stack_tab . size ( ) ; + + i )
delete block_stack_tab [ i ] . out_stream ;
block_stack_tab . clear ( ) ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : ClearForStack ( )
2012-02-24 13:04:36 +01:00
{
for ( size_t i = 0 ; i < stack_tab . size ( ) ; + + i )
2012-02-25 04:29:44 +01:00
RemoveStackFunData ( stack_tab [ i ] ) ;
2012-02-24 13:04:36 +01:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : ClearStream ( StreamType & str )
2011-01-26 13:42:49 +01:00
{
2021-07-12 23:00:11 +02:00
if constexpr ( is_pikotools_stream )
{
2021-06-20 16:54:55 +02:00
str . clear ( ) ;
2021-07-12 23:00:11 +02:00
}
else
{
2011-01-26 13:42:49 +01:00
str . str ( L " " ) ;
2021-07-12 23:00:11 +02:00
}
2011-01-26 13:42:49 +01:00
}
2010-11-22 02:23:32 +01:00
2021-06-20 16:54:55 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CopyStreamToString ( StreamType & src_stream , std : : wstring & dst_string )
2021-06-20 16:54:55 +02:00
{
if constexpr ( sizeof ( wchar_t ) = = sizeof ( typename StreamType : : char_type ) )
{
2021-07-12 23:00:11 +02:00
if constexpr ( is_pikotools_stream )
{
2021-06-20 16:54:55 +02:00
src_stream . to_str ( dst_string ) ;
2021-07-12 23:00:11 +02:00
}
else
{
2021-06-20 16:54:55 +02:00
dst_string = src_stream . str ( ) ;
2021-07-12 23:00:11 +02:00
}
2021-06-20 16:54:55 +02:00
}
else
{
2021-07-12 23:00:11 +02:00
if constexpr ( is_pikotools_stream )
{
2021-06-20 16:54:55 +02:00
src_stream . to_str ( dst_string ) ;
2021-07-12 23:00:11 +02:00
}
else
{
2021-06-20 16:54:55 +02:00
std : : string tmp = src_stream . str ( ) ;
pt : : utf8_to_wide ( tmp , dst_string ) ;
2021-07-12 23:00:11 +02:00
}
2021-06-20 16:54:55 +02:00
}
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CopyStream ( StreamType & src_stream , StreamType & dst_stream )
2021-06-20 16:54:55 +02:00
{
2021-07-12 23:00:11 +02:00
if constexpr ( is_pikotools_stream )
{
2021-06-20 16:54:55 +02:00
dst_stream < < src_stream ;
2021-07-12 23:00:11 +02:00
}
else
{
2021-06-20 16:54:55 +02:00
dst_stream < < src_stream . str ( ) ;
2021-07-12 23:00:11 +02:00
}
2021-06-20 16:54:55 +02:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CopyStream ( pt : : WTextStream & src_stream , StreamType & dst_stream , bool should_escape )
2021-06-20 16:54:55 +02:00
{
2021-07-12 23:00:11 +02:00
if constexpr ( is_autoescape_stream )
2021-06-20 16:54:55 +02:00
{
2021-07-12 23:00:11 +02:00
dst_stream . Escape ( should_escape ) ;
dst_stream < < src_stream ;
2021-06-20 16:54:55 +02:00
}
else
{
2021-07-12 23:00:11 +02:00
if constexpr ( is_pikotools_stream )
2021-06-20 16:54:55 +02:00
{
2021-07-12 23:00:11 +02:00
dst_stream < < src_stream ;
}
else
{
if constexpr ( sizeof ( char ) = = sizeof ( typename StreamType : : char_type ) )
{
wide_stream_to_utf8 ( src_stream , dst_stream , false ) ;
}
else
{
dst_stream < < src_stream . to_str ( ) ;
}
2021-06-20 16:54:55 +02:00
}
}
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : RemoveStackFunData ( Stack & s )
2012-02-25 04:29:44 +01:00
{
2014-10-19 07:42:25 +02:00
if ( s . fun_data & & s . auto_remove )
2012-02-25 04:29:44 +01:00
{
2012-02-27 18:39:46 +01:00
delete s . fun_data ;
s . fun_data = 0 ;
2012-02-25 04:29:44 +01:00
}
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
2011-04-26 19:17:06 +02:00
template < class CharType >
2021-07-12 23:00:11 +02:00
CharType Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : ToLower ( CharType c )
2011-04-26 19:17:06 +02:00
{
if ( c > = ' A ' & & c < = ' Z ' )
return c - ' A ' + ' a ' ;
return c ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : ConvertToBool ( const std : : wstring & str )
2015-03-08 03:31:21 +01:00
{
2021-05-23 10:02:51 +02:00
return ! str . empty ( ) ;
2015-03-08 03:31:21 +01:00
}
2014-10-17 23:36:55 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : SetMax ( size_t max_items_ , size_t max_for_items_ )
2010-11-22 02:23:32 +01:00
{
max_items = max_items_ ;
max_for_items = max_for_items_ ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : RecognizeSpecialChars ( bool spec )
2010-11-22 02:23:32 +01:00
{
special_chars = spec ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : TrimWhite ( bool trim )
2010-11-22 02:23:32 +01:00
{
trim_white = trim ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : SkipNewLine ( bool skip )
2010-11-22 02:23:32 +01:00
{
skip_new_line = skip ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : SetMaxFilters ( size_t new_len )
2011-01-26 13:42:49 +01:00
{
// the table will be resized when Generate() method is called
filter_size = new_len ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : SetStackSize ( size_t new_stack_size )
2012-02-27 18:39:46 +01:00
{
// the stack will be resized when Generate() method is called
stack_size = new_stack_size ;
}
2013-11-07 11:16:10 +01:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : Generate ( )
2010-11-22 02:23:32 +01:00
{
2011-04-26 19:17:06 +02:00
if ( is_generator_working )
2011-01-26 13:42:49 +01:00
{
2013-11-07 11:16:10 +01:00
CreateMsg ( L " generator busy " ) ;
2011-01-26 13:42:49 +01:00
return ;
}
2010-11-25 23:39:58 +01:00
break_generating = false ;
current_item = 0 ;
2012-02-27 18:39:46 +01:00
// in the case that there something has left on the stack
// from previous call to Generate()
// (an exception could have been thrown)
2014-10-17 23:36:55 +02:00
ClearForStack ( ) ;
2012-02-27 18:39:46 +01:00
2011-01-26 13:42:49 +01:00
ResizeFilterTab ( ) ;
2012-02-27 18:39:46 +01:00
ResizeStack ( ) ;
2014-10-17 23:36:55 +02:00
ResizeBlockStack ( ) ;
2021-05-28 16:10:16 +02:00
ResizeEzcFrameStack ( ) ;
2011-01-26 13:42:49 +01:00
filter_index = 0 ;
2012-02-27 18:39:46 +01:00
stack_index = 0 ;
2021-07-06 23:56:29 +02:00
ezc_frames_stack_index = 0 ;
2014-10-17 23:36:55 +02:00
block_stack_index = 0 ;
2010-11-25 23:39:58 +01:00
2014-10-17 23:36:55 +02:00
if ( ppattern )
2011-01-26 13:42:49 +01:00
{
try
{
2011-04-26 19:17:06 +02:00
is_generator_working = true ;
2014-10-17 23:36:55 +02:00
MakeText ( ppattern - > item_root ) ;
2015-11-12 10:53:20 +01:00
// !! IMPROVE ME we can print an error message if the stacks are not empty
// (some [end] statements has been omited)
2011-04-26 19:17:06 +02:00
is_generator_working = false ;
2011-01-26 13:42:49 +01:00
}
catch ( . . . )
{
2011-04-26 19:17:06 +02:00
is_generator_working = false ;
2011-01-26 13:42:49 +01:00
throw ;
}
}
2010-11-25 23:39:58 +01:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : Generate ( StreamType & out )
2010-11-25 23:39:58 +01:00
{
2015-11-12 10:53:20 +01:00
output_stream = & out ;
2021-07-12 23:00:11 +02:00
output_frames_streams = nullptr ;
2014-10-17 23:36:55 +02:00
Generate ( ) ;
2011-01-26 13:42:49 +01:00
}
2010-11-22 02:23:32 +01:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : Generate ( StreamType & out , OutStreams < StreamType , is_pikotools_stream > & out_streams )
2013-11-07 11:16:10 +01:00
{
2015-11-12 10:53:20 +01:00
output_stream = & out ;
2021-05-28 16:10:16 +02:00
output_frames_streams = & out_streams ;
2014-10-17 23:36:55 +02:00
Generate ( ) ;
2013-11-07 11:16:10 +01:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : Generate ( OutStreams < StreamType , is_pikotools_stream > & out_streams )
2013-11-07 11:16:10 +01:00
{
2021-07-12 23:00:11 +02:00
output_stream = nullptr ;
2021-05-28 16:10:16 +02:00
output_frames_streams = & out_streams ;
2014-10-17 23:36:55 +02:00
Generate ( ) ;
2013-11-07 11:16:10 +01:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : IsTestingFunctionExistence ( )
2021-07-02 20:23:20 +02:00
{
return is_generating_if_def | | is_generating_if_not_def ;
}
2015-06-14 20:20:00 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CheckBlockArgument ( int arg_index , FindHelper & find_helper )
2011-01-26 13:42:49 +01:00
{
2021-05-23 10:02:51 +02:00
if ( arg_index < 0 )
2015-06-14 20:20:00 +02:00
return false ;
// it's a numeric function -- an argument to a block e.g.: [1]
if ( block_stack_index > 0 )
2014-10-17 23:36:55 +02:00
{
2015-06-14 20:20:00 +02:00
BlockStack & block_stack = block_stack_tab [ block_stack_index - 1 ] ;
2013-11-07 11:16:10 +01:00
2021-05-23 10:02:51 +02:00
if ( size_t ( arg_index ) < block_stack . args . size ( ) )
2014-10-17 23:36:55 +02:00
{
2021-06-16 14:16:49 +02:00
find_helper . variable = & block_stack . args [ arg_index ] ;
2021-05-23 10:02:51 +02:00
return true ;
2014-10-17 23:36:55 +02:00
}
}
2013-11-07 11:16:10 +01:00
2021-05-23 10:02:51 +02:00
return false ;
2015-06-14 20:20:00 +02:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : FindInCache ( Item : : Function & item_fun , FindHelper & find_helper )
2015-06-14 20:20:00 +02:00
{
2014-10-19 23:09:34 +02:00
if ( can_find_in_cache )
2014-10-17 23:36:55 +02:00
{
2015-06-14 20:20:00 +02:00
if ( item_fun . base_obj )
{
2021-06-16 14:16:49 +02:00
find_helper . base_obj = reinterpret_cast < BaseObj < StreamType > * > ( item_fun . base_obj ) ;
find_helper . method_index = item_fun . method_index ;
2015-06-14 20:20:00 +02:00
return true ;
}
2014-10-19 23:09:34 +02:00
if ( item_fun . fun_cache )
{
2021-06-16 14:16:49 +02:00
find_helper . function = reinterpret_cast < typename Functions < StreamType > : : UserFunction * > ( item_fun . fun_cache ) ;
2014-10-19 23:09:34 +02:00
return true ;
}
2013-11-07 11:16:10 +01:00
2014-10-19 23:09:34 +02:00
if ( item_fun . item_block )
{
2021-06-16 14:16:49 +02:00
find_helper . item_block = item_fun . item_block ;
2014-10-19 23:09:34 +02:00
return true ;
}
2014-10-17 23:36:55 +02:00
}
2013-11-07 11:16:10 +01:00
2014-10-17 23:36:55 +02:00
return false ;
2010-11-22 02:23:32 +01:00
}
2014-10-17 23:36:55 +02:00
2021-06-16 14:16:49 +02:00
# ifdef EZC_HAS_MORM_LIBRARY
2021-05-31 18:37:09 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : FindInModels ( FindHelper & find_helper )
2021-05-31 18:37:09 +02:00
{
if ( pmodels )
{
2021-07-01 23:21:20 +02:00
morm : : Wrapper * m = pmodels - > Find ( * find_helper . fun_name ) ;
2021-05-31 18:37:09 +02:00
if ( m )
{
2021-07-01 23:21:20 +02:00
find_helper . wrapper = m ;
2021-05-31 18:37:09 +02:00
return true ;
}
}
return false ;
}
2021-06-16 14:16:49 +02:00
# endif
2021-05-31 18:37:09 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : FindInFunctionsAndBlocks ( const std : : wstring & name , FindHelper & find_helper )
2013-11-07 11:16:10 +01:00
{
2015-06-14 20:20:00 +02:00
if ( pobjects )
{
2021-06-16 14:16:49 +02:00
typename Objects < StreamType > : : Iterator i = pobjects - > Find ( name , find_helper . method_index ) ;
2015-06-14 20:20:00 +02:00
if ( i ! = pobjects - > End ( ) )
{
2021-06-16 14:16:49 +02:00
find_helper . base_obj = * i ;
2015-06-14 20:20:00 +02:00
return true ;
}
}
2014-10-17 23:36:55 +02:00
if ( pfunctions )
{
2014-10-18 00:14:28 +02:00
typename Functions < StreamType > : : Iterator i = pfunctions - > Find ( name ) ;
2013-11-07 11:16:10 +01:00
2014-10-17 23:36:55 +02:00
if ( i ! = pfunctions - > End ( ) )
{
2021-06-16 14:16:49 +02:00
find_helper . function = & i - > second ;
2014-10-17 23:36:55 +02:00
return true ;
}
}
2013-11-07 11:16:10 +01:00
2014-10-17 23:36:55 +02:00
if ( pblocks )
{
Blocks : : Iterator i = pblocks - > Find ( name ) ;
2010-11-22 02:23:32 +01:00
2014-10-17 23:36:55 +02:00
if ( i ! = pblocks - > End ( ) )
{
2021-06-16 14:16:49 +02:00
find_helper . item_block = & i - > second ;
2014-10-17 23:36:55 +02:00
return true ;
}
}
2010-11-22 02:23:32 +01:00
2014-10-17 23:36:55 +02:00
return false ;
}
2010-11-22 02:23:32 +01:00
2010-11-25 23:39:58 +01:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : FindInVariables ( const std : : wstring & name , FindHelper & find_helper )
2010-11-22 02:23:32 +01:00
{
2021-05-23 10:02:51 +02:00
if ( pvars )
2010-11-22 02:23:32 +01:00
{
2021-05-23 10:02:51 +02:00
Vars : : iterator i = pvars - > find ( name ) ;
2014-10-17 23:36:55 +02:00
2021-05-23 10:02:51 +02:00
if ( i ! = pvars - > end ( ) )
{
2021-06-16 14:16:49 +02:00
find_helper . variable = & ( i - > second ) ;
2021-05-23 10:02:51 +02:00
return true ;
}
2010-11-25 23:39:58 +01:00
}
2021-05-23 10:02:51 +02:00
return false ;
2014-10-17 23:36:55 +02:00
}
2021-06-16 14:16:49 +02:00
2021-05-23 10:02:51 +02:00
/*
* 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
*/
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : Find ( Item : : Function & item_fun , FindHelper & find_helper )
2021-06-16 14:16:49 +02:00
{
# ifdef EZC_HAS_MORM_LIBRARY
2021-06-19 20:18:30 +02:00
if ( FindInModels ( find_helper ) )
2021-06-16 14:16:49 +02:00
return true ;
2021-06-20 16:54:55 +02:00
2021-07-02 20:23:20 +02:00
if ( ! item_fun . fields . empty ( ) & & ! IsTestingFunctionExistence ( ) )
2021-06-20 16:54:55 +02:00
{
CreateMsg ( L " unknown model " , find_helper . fun_name - > c_str ( ) ) ;
return false ;
}
2021-06-16 14:16:49 +02:00
# endif
2015-06-14 20:20:00 +02:00
2021-06-16 14:16:49 +02:00
if ( CheckBlockArgument ( item_fun . arg , find_helper ) )
2014-10-17 23:36:55 +02:00
return true ;
2021-06-16 14:16:49 +02:00
if ( FindInCache ( item_fun , find_helper ) )
2014-10-17 23:36:55 +02:00
return true ;
2021-06-19 20:18:30 +02:00
if ( FindInFunctionsAndBlocks ( * find_helper . fun_name , find_helper ) )
2014-10-17 23:36:55 +02:00
return true ;
2021-06-19 20:18:30 +02:00
if ( FindInVariables ( * find_helper . fun_name , find_helper ) )
2021-06-16 14:16:49 +02:00
return true ;
2014-10-17 23:36:55 +02:00
2021-07-02 20:23:20 +02:00
if ( ! IsTestingFunctionExistence ( ) )
CreateMsg ( L " unknown function " , find_helper . fun_name - > c_str ( ) ) ;
2021-06-16 14:16:49 +02:00
return false ;
2010-11-22 02:23:32 +01:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : PrepareEnvStruct ( FunInfo < StreamType > & info )
2010-11-22 02:23:32 +01:00
{
info . Clear ( ) ;
2011-01-15 00:59:30 +01:00
2021-07-02 20:23:20 +02:00
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 ;
}
2012-02-24 13:04:36 +01:00
2011-04-26 19:17:06 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CallFunction ( typename Functions < StreamType > : : UserFunction & function , FunInfo < StreamType > & info )
2021-07-02 20:23:20 +02:00
{
PrepareEnvStruct ( info ) ;
( function ) ( info ) ;
2011-04-26 19:17:06 +02:00
last_res = info . res ;
2010-11-22 02:23:32 +01:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CallFunction ( typename Functions < StreamType > : : UserFunction & function ,
2014-10-28 18:46:24 +01:00
std : : vector < Var > & parameters ,
2014-10-17 23:36:55 +02:00
StreamType & out_stream ,
const StreamType & in_stream )
2010-11-22 02:23:32 +01:00
{
2021-07-02 20:23:20 +02:00
if ( ! IsTestingFunctionExistence ( ) )
2010-11-22 02:23:32 +01:00
{
2021-07-02 20:23:20 +02:00
if ( parameters . empty ( ) )
{
FunInfo < StreamType > info ( out_stream , parameters , empty , in_stream , stack_tab [ stack_index - 1 ] , * stack_tab [ stack_index - 1 ] . item ) ;
CallFunction ( function , info ) ;
}
else
{
FunInfo < StreamType > info ( out_stream , parameters , parameters [ 0 ] . str , in_stream , stack_tab [ stack_index - 1 ] , * stack_tab [ stack_index - 1 ] . item ) ;
CallFunction ( function , info ) ;
}
2010-11-22 02:23:32 +01:00
}
2011-01-26 13:42:49 +01:00
}
2010-11-22 02:23:32 +01:00
2011-01-26 13:42:49 +01:00
2014-10-28 18:46:24 +01:00
2015-06-14 20:20:00 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CallObject ( BaseObj < StreamType > & base_obj , int method_index , FunInfo < StreamType > & info )
2015-06-14 20:20:00 +02:00
{
2021-07-02 20:23:20 +02:00
PrepareEnvStruct ( info ) ;
2021-06-16 14:16:49 +02:00
base_obj . CallFun ( method_index , info ) ;
2015-06-14 20:20:00 +02:00
last_res = info . res ;
}
2021-05-31 18:37:09 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : HasParam ( std : : vector < Var > & parameters , const wchar_t * param1 , const wchar_t * param2 )
2021-05-31 18:37:09 +02:00
{
for ( Var & var : parameters )
{
if ( ! var . is_function )
{
2021-06-27 22:42:00 +02:00
if ( var . str = = param1 | | ( param2 & & var . str = = param2 ) )
2021-05-31 18:37:09 +02:00
{
2021-06-27 22:42:00 +02:00
return true ;
2021-05-31 18:37:09 +02:00
}
}
}
2021-06-27 22:42:00 +02:00
return false ;
2021-05-31 18:37:09 +02:00
}
2021-06-27 22:42:00 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : ShouldMakeSpaceDump ( std : : vector < Var > & parameters )
2021-06-22 18:01:47 +02:00
{
2021-06-27 22:42:00 +02:00
return HasParam ( parameters , L " dump " , L " dump_to_space " ) ;
}
2021-06-22 18:01:47 +02:00
2021-06-27 22:42:00 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : ShouldMakeJsonDump ( std : : vector < Var > & parameters )
2021-06-27 22:42:00 +02:00
{
return HasParam ( parameters , L " dump_to_json " ) ;
2021-06-22 18:01:47 +02:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : IsCurrentParam ( std : : vector < Var > & parameters )
2021-06-22 18:01:47 +02:00
{
2021-06-27 22:42:00 +02:00
return HasParam ( parameters , L " current " ) ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : IsPrettyPrint ( std : : vector < Var > & parameters )
2021-06-27 22:42:00 +02:00
{
return HasParam ( parameters , L " pretty " ) ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : DumpSpaceIfNeeded ( std : : vector < Var > & parameters , StreamType & out_stream , pt : : Space * space )
2021-06-27 22:42:00 +02:00
{
bool dump_space = ShouldMakeSpaceDump ( parameters ) ;
bool dump_json = ShouldMakeJsonDump ( parameters ) ;
if ( dump_space | | dump_json )
2021-06-22 18:01:47 +02:00
{
2021-06-27 22:42:00 +02:00
bool pretty = IsPrettyPrint ( parameters ) ;
if ( dump_space )
2021-06-22 18:01:47 +02:00
{
2021-06-27 22:42:00 +02:00
space - > serialize_to_space_stream ( out_stream , pretty ) ;
}
else
if ( dump_json )
{
space - > serialize_to_json_stream ( out_stream , pretty ) ;
2021-06-22 18:01:47 +02:00
}
}
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : DumpModelIfNeeded ( morm : : Model & model , std : : vector < Var > & parameters , StreamType & out_stream )
2021-07-01 23:21:20 +02:00
{
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 ;
}
}
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : PrintDate ( pt : : Date * date , std : : vector < Var > parameters , StreamType & out_stream )
2021-07-01 23:21:20 +02:00
{
2021-07-06 21:47:42 +02:00
bool is_roman = HasParam ( parameters , L " roman " ) ;
bool is_no_sec = HasParam ( parameters , L " no_sec " ) ;
2021-07-01 23:21:20 +02:00
2021-07-06 21:47:42 +02:00
date - > Serialize ( out_stream , is_roman , ! is_no_sec ) ;
2021-07-01 23:21:20 +02:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : PrintDatePart ( pt : : Date * date , const std : : wstring & field , std : : vector < Var > parameters , StreamType & out_stream )
2021-07-01 23:21:20 +02:00
{
2021-07-02 20:23:20 +02:00
bool is_test = IsTestingFunctionExistence ( ) ;
2021-07-01 23:21:20 +02:00
if ( field = = L " year " )
2021-07-02 20:23:20 +02:00
{
if ( ! is_test )
out_stream < < date - > year ;
}
2021-07-01 23:21:20 +02:00
else
if ( field = = L " month " )
2021-07-02 20:23:20 +02:00
{
if ( ! is_test )
2021-07-06 21:47:42 +02:00
{
bool is_roman = HasParam ( parameters , L " roman " ) ;
if ( is_roman )
pt : : Date : : SerializeMonthAsRoman ( out_stream , date - > month ) ;
else
out_stream < < date - > month ;
}
2021-07-02 20:23:20 +02:00
}
2021-07-01 23:21:20 +02:00
else
if ( field = = L " day " )
2021-07-02 20:23:20 +02:00
{
if ( ! is_test )
out_stream < < date - > day ;
}
2021-07-01 23:21:20 +02:00
else
if ( field = = L " hour " )
2021-07-02 20:23:20 +02:00
{
if ( ! is_test )
out_stream < < date - > hour ;
}
2021-07-01 23:21:20 +02:00
else
if ( field = = L " min " )
2021-07-02 20:23:20 +02:00
{
if ( ! is_test )
out_stream < < date - > min ;
}
2021-07-01 23:21:20 +02:00
else
if ( field = = L " sec " )
2021-07-02 20:23:20 +02:00
{
if ( ! is_test )
out_stream < < date - > sec ;
}
2021-07-01 23:21:20 +02:00
else
2021-07-02 20:23:20 +02:00
{
2021-07-01 23:21:20 +02:00
return false ;
2021-07-02 20:23:20 +02:00
}
2021-07-01 23:21:20 +02:00
return true ;
}
2021-06-25 16:16:30 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CallDate ( FindHelper & find_helper , std : : vector < std : : wstring > & fields , std : : vector < Var > parameters , StreamType & out_stream )
2021-07-02 20:23:20 +02:00
{
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 ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CallSpaceObjectForLastField ( std : : vector < Var > & parameters , StreamType & out_stream , pt : : Space * space )
2021-06-25 16:16:30 +02:00
{
2021-07-02 20:23:20 +02:00
if ( ! IsTestingFunctionExistence ( ) )
{
// CHECKME should we convert the last value to last_res?
DumpSpaceIfNeeded ( parameters , out_stream , space ) ;
}
2021-06-25 16:16:30 +02:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
pt : : Space * Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CallSpaceObjectForMiddleField ( std : : wstring & root_space_name , std : : vector < std : : wstring > & fields , size_t field_index , pt : : Space * space )
2021-06-25 16:16:30 +02:00
{
std : : wstring & next_field = fields [ field_index ] ;
2021-06-27 22:42:00 +02:00
space = space - > get_space ( next_field ) ;
2021-06-25 16:16:30 +02:00
2021-07-02 20:23:20 +02:00
if ( ! space & & ! IsTestingFunctionExistence ( ) )
2021-06-25 16:16:30 +02:00
{
CreateMsg ( L " cannot find space field: " , root_space_name , fields , field_index + 1 ) ;
}
return space ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CallSpaceTableForLastField ( morm : : SpaceWrapper & space_wrapper , std : : vector < Var > & parameters , StreamType & out_stream ,
2021-06-25 16:16:30 +02:00
pt : : Space * space , size_t model_wrapper_space_table_index )
{
pt : : Space : : TableType * table = space - > get_table ( ) ;
2021-07-02 20:23:20 +02:00
if ( is_generating_for )
2021-06-25 16:16:30 +02:00
{
// we are in [for...]statement, increment iterator and check the range
2021-07-01 23:21:20 +02:00
space_wrapper . increment_iterator ( model_wrapper_space_table_index , table - > size ( ) ) ;
2021-08-13 21:44:07 +02:00
space_wrapper . invalidate_iterators ( model_wrapper_space_table_index + 1 ) ;
2021-07-01 23:21:20 +02:00
size_t iterator_value = space_wrapper . get_space_iterator_value ( model_wrapper_space_table_index ) ;
2021-06-25 16:16:30 +02:00
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
2021-07-02 20:23:20 +02:00
// if we are in [if-def...] - then last_res is set later in MakeTextIfDef(Item & item) when Call() method returns
2021-06-25 16:16:30 +02:00
last_res = ! table - > empty ( ) ;
}
2021-07-02 20:23:20 +02:00
if ( ! IsTestingFunctionExistence ( ) )
2021-06-25 16:16:30 +02:00
{
2021-07-02 20:23:20 +02:00
DumpSpaceIfNeeded ( parameters , out_stream , space ) ;
2021-06-25 16:16:30 +02:00
2021-07-02 20:23:20 +02:00
if ( IsCurrentParam ( parameters ) )
2021-06-25 16:16:30 +02:00
{
2021-07-02 20:23:20 +02:00
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 ) ;
}
2021-06-25 16:16:30 +02:00
}
}
}
2021-07-02 20:23:20 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
pt : : Space * Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CallSpaceTableForMiddleField ( morm : : SpaceWrapper & space_wrapper , std : : wstring & root_space_name , std : : vector < std : : wstring > & fields ,
2021-06-25 16:16:30 +02:00
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
2021-07-01 23:21:20 +02:00
size_t iterator_value = space_wrapper . get_space_iterator_value ( model_wrapper_space_table_index ) ;
2021-06-25 16:16:30 +02:00
if ( iterator_value < table - > size ( ) )
{
space = ( * table ) [ iterator_value ] ;
}
else
{
2021-07-02 20:23:20 +02:00
// this message can be print even for [if-def...]
2021-06-25 16:16:30 +02:00
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 ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : PrintLastSpaceField ( pt : : Space * space , std : : vector < Var > & parameters , StreamType & out_stream )
2021-07-02 20:23:20 +02:00
{
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 ) ;
}
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CallSpace ( FindHelper & find_helper , std : : vector < std : : wstring > & fields , std : : vector < Var > & parameters , StreamType & out_stream )
2021-06-22 18:01:47 +02:00
{
2021-07-01 23:21:20 +02:00
morm : : SpaceWrapper * space_wrapper = find_helper . wrapper - > space_wrapper ;
pt : : Space * space = space_wrapper - > get_space ( ) ;
2021-06-22 18:01:47 +02:00
last_res = false ;
2021-07-01 23:21:20 +02:00
size_t field_index = find_helper . field_index ;
2021-06-22 18:01:47 +02:00
2021-06-25 16:16:30 +02:00
/*
*
* 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 )
2021-06-22 18:01:47 +02:00
{
2021-06-25 16:16:30 +02:00
bool is_last_field = ( field_index = = fields . size ( ) ) ;
2021-06-22 18:01:47 +02:00
if ( space - > is_object ( ) )
{
if ( is_last_field )
{
2021-06-25 16:16:30 +02:00
CallSpaceObjectForLastField ( parameters , out_stream , space ) ;
2021-06-22 18:01:47 +02:00
}
else
{
2021-06-25 16:16:30 +02:00
space = CallSpaceObjectForMiddleField ( * find_helper . fun_name , fields , field_index , space ) ;
2021-06-22 18:01:47 +02:00
}
2021-06-23 21:56:04 +02:00
2021-06-25 16:16:30 +02:00
field_index + = 1 ;
2021-06-22 18:01:47 +02:00
}
else
if ( space - > is_table ( ) )
{
2021-07-01 23:21:20 +02:00
size_t model_wrapper_space_table_index = field_index - find_helper . field_index ;
2021-06-22 18:01:47 +02:00
2021-07-01 23:21:20 +02:00
if ( model_wrapper_space_table_index < space_wrapper - > space_indices_table_size ( ) )
2021-06-22 18:01:47 +02:00
{
2021-06-25 16:16:30 +02:00
if ( is_last_field )
2021-06-22 18:01:47 +02:00
{
2021-07-01 23:21:20 +02:00
CallSpaceTableForLastField ( * space_wrapper , parameters , out_stream , space , model_wrapper_space_table_index ) ;
2021-06-25 16:16:30 +02:00
field_index + = 1 ;
2021-06-22 18:01:47 +02:00
}
else
{
2021-07-01 23:21:20 +02:00
space = CallSpaceTableForMiddleField ( * space_wrapper , * find_helper . fun_name , fields , field_index , space , model_wrapper_space_table_index ) ;
2021-06-25 16:16:30 +02:00
// don't increment field_index
2021-06-22 18:01:47 +02:00
}
}
else
{
2021-06-25 16:16:30 +02:00
CreateMsg ( L " " , * find_helper . fun_name , fields , field_index , L " exceeded the maximum number of fields for a space object " ) ;
2021-07-02 20:23:20 +02:00
space = nullptr ;
2021-06-22 18:01:47 +02:00
}
}
else
{
if ( is_last_field )
{
2021-07-02 20:23:20 +02:00
if ( ! IsTestingFunctionExistence ( ) )
{
PrintLastSpaceField ( space , parameters , out_stream ) ;
}
2021-06-25 16:16:30 +02:00
field_index + = 1 ;
2021-06-22 18:01:47 +02:00
}
else
{
2021-07-02 20:23:20 +02:00
if ( ! IsTestingFunctionExistence ( ) )
{
CreateMsg ( L " " , * find_helper . fun_name , fields , field_index , L " of a space is not an object nor a table " ) ;
}
space = nullptr ;
2021-06-22 18:01:47 +02:00
}
}
}
2021-07-02 20:23:20 +02:00
return space ! = nullptr ;
2021-06-22 18:01:47 +02:00
}
2021-05-31 18:37:09 +02:00
2021-06-16 14:16:49 +02:00
# ifdef EZC_HAS_MORM_LIBRARY
2021-05-31 18:37:09 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CallModelField ( morm : : Model & model , const std : : wstring & field , std : : vector < Var > parameters , StreamType & out_stream , const StreamType & in_stream )
2021-05-31 18:37:09 +02:00
{
2021-06-16 14:16:49 +02:00
/*
* if ' field ' is a POD type then ' str ' will be used in get_raw_value ( )
2021-06-20 16:54:55 +02:00
* if ' field ' is a getter method with pt : : Stream then ' str ' will be used too
2021-06-16 14:16:49 +02:00
* if ' field ' is a getter method which takes FunInfo < > then out_stream will be used and ' str ' will be empty
*
*/
2021-06-20 16:54:55 +02:00
pt : : WTextStream str ;
2021-06-19 20:18:30 +02:00
bool found = false ;
2021-05-31 18:37:09 +02:00
2021-06-16 14:16:49 +02:00
if ( parameters . empty ( ) )
2021-05-31 18:37:09 +02:00
{
2021-06-16 14:16:49 +02:00
FunInfo < StreamType > info ( out_stream , parameters , empty , in_stream , stack_tab [ stack_index - 1 ] , * stack_tab [ stack_index - 1 ] . item ) ;
2021-06-19 20:18:30 +02:00
found = model . get_raw_value ( nullptr , field . c_str ( ) , nullptr , info , str , false ) ;
2021-06-16 14:16:49 +02:00
last_res = info . res ;
2021-05-31 18:37:09 +02:00
}
else
{
2021-06-16 14:16:49 +02:00
FunInfo < StreamType > info ( out_stream , parameters , parameters [ 0 ] . str , in_stream , stack_tab [ stack_index - 1 ] , * stack_tab [ stack_index - 1 ] . item ) ;
2021-06-19 20:18:30 +02:00
found = model . get_raw_value ( nullptr , field . c_str ( ) , nullptr , info , str , false ) ;
2021-06-16 14:16:49 +02:00
last_res = info . res ;
}
2021-05-31 18:37:09 +02:00
2021-06-20 16:54:55 +02:00
if ( found & & ! str . empty ( ) )
2021-06-19 20:18:30 +02:00
{
2021-07-02 20:23:20 +02:00
bool no_escape = HasParam ( parameters , L " raw " , L " noescape " ) ;
CopyStream ( str , out_stream , ! no_escape ) ;
2021-06-19 20:18:30 +02:00
}
return found ;
2021-06-16 14:16:49 +02:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CallModel ( morm : : Model & model , FindHelper & find_helper , std : : vector < std : : wstring > & fields ,
2021-07-02 20:23:20 +02:00
std : : vector < Var > parameters , StreamType & out_stream , const StreamType & in_stream )
2021-06-16 14:16:49 +02:00
{
2021-07-02 20:23:20 +02:00
bool found = true ;
2021-07-01 23:21:20 +02:00
if ( find_helper . field_index = = fields . size ( ) )
{
// all fields items are models or models containers
2021-07-02 20:23:20 +02:00
if ( ! IsTestingFunctionExistence ( ) )
{
DumpModelIfNeeded ( model , parameters , out_stream ) ;
}
2021-07-01 23:21:20 +02:00
}
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 ) )
{
2021-07-02 20:23:20 +02:00
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 ;
2021-07-01 23:21:20 +02:00
}
}
else
{
2021-07-02 20:23:20 +02:00
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 ;
2021-07-01 23:21:20 +02:00
}
2021-07-02 20:23:20 +02:00
return found ;
2021-07-01 23:21:20 +02:00
}
2021-06-16 14:16:49 +02:00
2021-07-01 23:21:20 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : FindLastModelWrapper ( FindHelper & find_helper , std : : vector < std : : wstring > & fields )
2021-07-01 23:21:20 +02:00
{
for ( find_helper . field_index = 0 ; find_helper . field_index < fields . size ( ) & & find_helper . wrapper - > has_model_object ( ) ; + + find_helper . field_index )
2021-06-16 14:16:49 +02:00
{
2021-07-01 23:21:20 +02:00
std : : wstring & field = fields [ find_helper . field_index ] ;
morm : : Wrapper * child_wrapper = find_helper . wrapper - > find_child ( field ) ;
2021-06-16 14:16:49 +02:00
2021-07-01 23:21:20 +02:00
if ( ! child_wrapper )
2021-05-31 18:37:09 +02:00
{
2021-07-01 23:21:20 +02:00
morm : : Model * model = nullptr ;
if ( find_helper . wrapper - > model )
{
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
}
2021-05-31 18:37:09 +02:00
2021-07-01 23:21:20 +02:00
if ( model )
2021-05-31 18:37:09 +02:00
{
2021-07-01 23:21:20 +02:00
morm : : Wrapper new_wrapper = model - > get_wrapper ( nullptr , field . c_str ( ) ) ;
2021-05-31 18:37:09 +02:00
2021-07-01 23:21:20 +02:00
if ( new_wrapper . has_object ( ) )
2021-05-31 18:37:09 +02:00
{
2021-07-01 23:21:20 +02:00
child_wrapper = find_helper . wrapper - > add_child ( field , new_wrapper ) ;
2021-05-31 18:37:09 +02:00
}
}
2021-06-16 14:16:49 +02:00
}
2021-05-31 18:37:09 +02:00
2021-07-01 23:21:20 +02:00
if ( ! child_wrapper )
2021-06-16 14:16:49 +02:00
break ;
2021-05-31 18:37:09 +02:00
2021-07-01 23:21:20 +02:00
find_helper . wrapper = child_wrapper ;
2021-06-16 14:16:49 +02:00
}
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CallWrapper ( FindHelper & find_helper , std : : vector < std : : wstring > & fields ,
2021-06-16 14:16:49 +02:00
std : : vector < Var > parameters , StreamType & out_stream , const StreamType & in_stream )
{
2021-07-02 20:23:20 +02:00
bool found = true ;
2021-06-16 14:16:49 +02:00
last_res = false ;
2021-07-01 23:21:20 +02:00
FindLastModelWrapper ( find_helper , fields ) ;
2021-06-16 14:16:49 +02:00
// if:
2021-07-01 23:21:20 +02:00
// 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
2021-06-16 14:16:49 +02:00
2021-07-01 23:21:20 +02:00
bool all_fields_known = ( find_helper . field_index = = fields . size ( ) ) ;
bool last_field_not_known = ( find_helper . field_index + 1 = = fields . size ( ) ) ;
2021-06-22 18:01:47 +02:00
2021-07-01 23:21:20 +02:00
if ( find_helper . wrapper - > space_wrapper )
2021-06-16 14:16:49 +02:00
{
2021-07-02 20:23:20 +02:00
found = CallSpace ( find_helper , fields , parameters , out_stream ) ;
2021-06-16 14:16:49 +02:00
}
2021-07-01 23:21:20 +02:00
if ( find_helper . wrapper - > date )
{
2021-07-02 20:23:20 +02:00
found = CallDate ( find_helper , fields , parameters , out_stream ) ;
2021-06-16 14:16:49 +02:00
}
2021-07-01 23:21:20 +02:00
if ( find_helper . wrapper - > model )
2021-06-16 14:16:49 +02:00
{
2021-07-02 20:23:20 +02:00
found = CallModel ( * find_helper . wrapper - > model , find_helper , fields , parameters , out_stream , in_stream ) ;
2021-07-01 23:21:20 +02:00
}
2021-06-23 06:53:43 +02:00
2021-07-01 23:21:20 +02:00
if ( find_helper . wrapper - > model_container_wrapper )
{
morm : : Model * model = find_helper . wrapper - > model_container_wrapper - > get_model ( ) ;
if ( model )
2021-06-16 14:16:49 +02:00
{
2021-07-02 20:23:20 +02:00
found = CallModel ( * model , find_helper , fields , parameters , out_stream , in_stream ) ;
2021-06-16 14:16:49 +02:00
}
else
2021-07-01 23:21:20 +02:00
{
if ( last_field_not_known )
{
2021-07-02 20:23:20 +02:00
// can be printed even for [if-def...]
2021-07-01 23:21:20 +02:00
CreateMsg ( L " model " , * find_helper . fun_name , fields , L " is not initialized, have you forgotten to use [for ...] statement? " ) ;
2021-07-02 20:23:20 +02:00
found = false ;
2021-07-01 23:21:20 +02:00
}
}
if ( all_fields_known )
2021-06-16 14:16:49 +02:00
{
2021-07-02 20:23:20 +02:00
if ( is_generating_for )
2021-06-23 06:53:43 +02:00
{
2021-07-01 23:21:20 +02:00
find_helper . wrapper - > model_container_wrapper - > increment_iterator ( ) ;
find_helper . wrapper - > clear_childs ( ) ;
last_res = find_helper . wrapper - > model_container_wrapper - > is_iterator_correct ( ) ;
2021-06-23 06:53:43 +02:00
}
else
{
2021-07-02 20:23:20 +02:00
// for [if-def...] last_res will be set later
2021-07-01 23:21:20 +02:00
last_res = ! find_helper . wrapper - > model_container_wrapper - > is_container_empty ( ) ;
2021-06-23 06:53:43 +02:00
}
2021-05-31 18:37:09 +02:00
}
}
2021-07-02 20:23:20 +02:00
return found ;
2021-05-31 18:37:09 +02:00
}
2021-07-01 23:21:20 +02:00
2021-06-16 14:16:49 +02:00
# endif
2021-05-31 18:37:09 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CallObject ( BaseObj < StreamType > & base_obj ,
2015-06-14 20:20:00 +02:00
int method_index ,
std : : vector < Var > & parameters ,
StreamType & out_stream ,
const StreamType & in_stream )
{
2021-07-02 20:23:20 +02:00
if ( ! IsTestingFunctionExistence ( ) )
2015-06-14 20:20:00 +02:00
{
2021-07-02 20:23:20 +02:00
if ( parameters . empty ( ) )
{
FunInfo < StreamType > 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 < StreamType > 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 ) ;
}
2015-06-14 20:20:00 +02:00
}
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CallBlock ( Item & item_block ,
2014-10-28 18:46:24 +01:00
std : : vector < Var > & parameters ,
2014-10-17 23:36:55 +02:00
StreamType & out_stream )
{
if ( block_stack_index > = block_stack_tab . size ( ) )
{
CreateMsg ( L " Generator exceeded allowed number of blocks " ) ;
return false ;
}
2021-07-02 20:23:20 +02:00
if ( ! IsTestingFunctionExistence ( ) )
{
StreamType * old_stream = output_stream ;
BlockStack & block_stack = block_stack_tab [ block_stack_index ] ;
2014-10-17 23:36:55 +02:00
2021-07-02 20:23:20 +02:00
block_stack . was_return = false ;
block_stack . args = parameters ;
2014-10-17 23:36:55 +02:00
2021-07-02 20:23:20 +02:00
output_stream = block_stack . out_stream ;
ClearStream ( * output_stream ) ;
block_stack_index + = 1 ;
2014-10-17 23:36:55 +02:00
2021-07-02 20:23:20 +02:00
MakeText ( item_block ) ;
2014-10-17 23:36:55 +02:00
2021-07-02 20:23:20 +02:00
CopyStream ( * output_stream , out_stream ) ;
// last_res is set by [return ...] statement or other last evaluated function
2014-10-17 23:36:55 +02:00
2021-07-02 20:23:20 +02:00
ClearStream ( * output_stream ) ;
output_stream = old_stream ;
block_stack_index - = 1 ;
}
2014-10-17 23:36:55 +02:00
return true ;
}
2011-01-26 13:42:49 +01:00
2011-04-26 19:17:06 +02:00
2021-05-23 10:02:51 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CallVariable ( Item : : Function & item_fun , Var & variable , std : : vector < Var > & parameters , StreamType & out_stream , const StreamType & in_stream )
2021-05-23 10:02:51 +02:00
{
2021-06-16 14:16:49 +02:00
if ( variable . is_function )
2021-05-23 10:02:51 +02:00
{
2021-06-16 14:16:49 +02:00
return Call ( item_fun , & variable . str , out_stream , false , in_stream ) ;
2021-05-23 10:02:51 +02:00
}
else
{
2021-07-02 20:23:20 +02:00
if ( ! IsTestingFunctionExistence ( ) )
{
out_stream < < variable . str ;
last_res = variable . res ;
}
2021-05-23 10:02:51 +02:00
return true ;
}
}
/*
* 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
*
* return : true if a function , variable or block was found and called ( evaluated )
*/
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : Call ( Item : : Function & item_fun ,
2021-05-23 10:02:51 +02:00
std : : wstring * fun_name ,
2014-10-17 23:36:55 +02:00
StreamType & out_stream ,
bool clear_out_stream ,
const StreamType & in_stream )
2011-01-26 13:42:49 +01:00
{
2021-06-16 14:16:49 +02:00
FindHelper find_helper ;
2014-10-28 18:46:24 +01:00
std : : vector < Var > parameters ;
2014-10-17 23:36:55 +02:00
if ( clear_out_stream )
ClearStream ( out_stream ) ;
2011-01-26 13:42:49 +01:00
2021-07-12 23:00:11 +02:00
if constexpr ( is_autoescape_stream )
out_stream . Escape ( true ) ;
2021-06-19 20:18:30 +02:00
find_helper . fun_name = fun_name ;
if ( ! find_helper . fun_name )
find_helper . fun_name = & item_fun . name ;
2021-05-31 18:37:09 +02:00
2021-06-19 20:18:30 +02:00
if ( ! Find ( item_fun , find_helper ) )
2021-06-16 14:16:49 +02:00
return false ;
2011-01-26 13:42:49 +01:00
2014-10-28 18:46:24 +01:00
parameters . resize ( item_fun . parameters . size ( ) ) ;
2014-10-17 23:36:55 +02:00
for ( size_t i = 0 ; i < item_fun . parameters . size ( ) ; + + i )
{
Item : : Function & fun_child = * item_fun . parameters [ i ] ;
2015-03-08 03:31:21 +01:00
if ( fun_child . is_function )
2014-10-17 23:36:55 +02:00
{
2014-10-28 18:46:24 +01:00
StreamType local_temp_stream ;
2021-05-23 10:02:51 +02:00
Call ( fun_child , nullptr , local_temp_stream , true , empty_stream ) ;
2014-10-17 23:36:55 +02:00
2021-06-20 16:54:55 +02:00
CopyStreamToString ( local_temp_stream , parameters [ i ] . str ) ;
2014-10-28 18:46:24 +01:00
parameters [ i ] . res = last_res ;
2014-10-17 23:36:55 +02:00
}
2014-10-28 18:46:24 +01:00
else
2014-10-17 23:36:55 +02:00
{
2015-03-08 03:31:21 +01:00
parameters [ i ] . str = fun_child . name ;
parameters [ i ] . res = ConvertToBool ( fun_child . name ) ;
2014-10-17 23:36:55 +02:00
}
}
2021-06-16 14:16:49 +02:00
# ifdef EZC_HAS_MORM_LIBRARY
2021-07-01 23:21:20 +02:00
if ( find_helper . wrapper )
2021-07-02 20:23:20 +02:00
return CallWrapper ( find_helper , item_fun . fields , parameters , out_stream , in_stream ) ;
2021-05-31 18:37:09 +02:00
else
2021-06-16 14:16:49 +02:00
# endif
if ( find_helper . base_obj )
CallObject ( * find_helper . base_obj , find_helper . method_index , parameters , out_stream , in_stream ) ;
2015-06-14 20:20:00 +02:00
else
2021-06-16 14:16:49 +02:00
if ( find_helper . function )
CallFunction ( * find_helper . function , parameters , out_stream , in_stream ) ;
2014-10-17 23:36:55 +02:00
else
2021-06-16 14:16:49 +02:00
if ( find_helper . item_block )
return CallBlock ( * find_helper . item_block , parameters , out_stream ) ;
2014-10-17 23:36:55 +02:00
else
2021-06-16 14:16:49 +02:00
if ( find_helper . variable )
return CallVariable ( item_fun , * find_helper . variable , parameters , out_stream , in_stream ) ;
2010-11-25 23:39:58 +01:00
2021-05-23 10:02:51 +02:00
return true ;
2010-11-22 02:23:32 +01:00
}
2010-11-25 23:39:58 +01:00
2011-04-26 19:17:06 +02:00
// return: true if a function or variable was found and called
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : Call ( Item : : Function & item_fun )
2011-01-15 00:59:30 +01:00
{
2021-05-23 10:02:51 +02:00
return Call ( item_fun , nullptr , stream_temp1 , true , empty_stream ) ;
2011-01-15 00:59:30 +01:00
}
2010-11-25 23:39:58 +01:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
wchar_t Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CreateSpecialChar ( wchar_t c )
2010-11-22 02:23:32 +01:00
{
wchar_t res = 0 ;
if ( c = = ' r ' )
res = ' \r ' ;
else
if ( c = = ' n ' )
res = ' \n ' ;
else
if ( c = = ' t ' )
res = ' \t ' ;
else
if ( c = = ' s ' )
res = ' ' ;
else
if ( c = = ' \\ ' )
res = ' \\ ' ;
return res ;
}
2010-11-25 02:55:32 +01:00
// a special character is precedeed by a slash '\'
// if the special character is unknown the first slash is printing
// so "\t" gives one character of code 9
// and "\x" gives "\x"
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
const wchar_t * Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : PrintSpecialChar ( const wchar_t * start , const wchar_t * end )
2010-11-22 02:23:32 +01:00
{
2010-11-25 02:55:32 +01:00
wchar_t special = 0 ;
2010-11-22 02:23:32 +01:00
2010-11-25 02:55:32 +01:00
if ( * start = = ' \\ ' & & ( start + 1 ) ! = end )
special = CreateSpecialChar ( * ( start + 1 ) ) ;
if ( special )
{
output_stream - > write ( & special , 1 ) ;
start + = 2 ;
}
else
{
if ( ! skip_new_line | | * start ! = 10 )
output_stream - > write ( start , 1 ) ;
start + = 1 ;
}
return start ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : PrintSpecialText ( const wchar_t * start , const wchar_t * end )
2010-11-25 02:55:32 +01:00
{
2013-11-07 11:16:10 +01:00
if ( output_stream )
2010-11-22 02:23:32 +01:00
{
2013-11-07 11:16:10 +01:00
while ( start ! = end )
{
const wchar_t * end2 = start ;
2010-11-22 02:23:32 +01:00
2013-11-07 11:16:10 +01:00
// looking for a first new line character or a special char
// (for new line only if skip_new_line is true)
while ( end2 ! = end & & * end2 ! = ' \\ ' & & ( ! skip_new_line | | * end2 ! = 10 ) )
end2 + = 1 ;
2010-11-22 02:23:32 +01:00
2013-11-07 11:16:10 +01:00
// printing the first part of the text
if ( start ! = end2 )
output_stream - > write ( start , end2 - start ) ;
2010-11-22 02:23:32 +01:00
2013-11-07 11:16:10 +01:00
start = end2 ;
// skipping one or more new line characters or special chars
// (new lines only if skip_new_line is true)
while ( start ! = end & & ( * start = = ' \\ ' | | ( skip_new_line & & * start = = 10 ) ) )
start = PrintSpecialChar ( start , end ) ;
}
2010-11-22 02:23:32 +01:00
}
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : PrintNormalText ( const wchar_t * start , const wchar_t * end )
2010-11-22 02:23:32 +01:00
{
2013-11-07 11:16:10 +01:00
if ( output_stream )
2010-11-22 02:23:32 +01:00
{
2013-11-07 11:16:10 +01:00
if ( skip_new_line )
2010-11-22 02:23:32 +01:00
{
2013-11-07 11:16:10 +01:00
while ( start ! = end )
{
const wchar_t * end2 = start ;
2010-11-25 02:55:32 +01:00
2013-11-07 11:16:10 +01:00
// looking for a first new line character
while ( end2 ! = end & & * end2 ! = 10 )
end2 + = 1 ;
2010-11-25 02:55:32 +01:00
2013-11-07 11:16:10 +01:00
// printing the first part of the text (until the new line)
if ( start ! = end2 )
output_stream - > write ( start , end2 - start ) ;
2010-11-25 02:55:32 +01:00
2013-11-07 11:16:10 +01:00
start = end2 ;
// skipping one or more new line characters
while ( start ! = end & & * start = = 10 )
start + = 1 ;
}
}
else
{
if ( start ! = end )
output_stream - > write ( start , end - start ) ;
2010-11-22 02:23:32 +01:00
}
}
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : IsWhite ( wchar_t c )
2014-10-11 21:56:48 +02:00
{
// 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 ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : TrimWhite ( const wchar_t * & start , const wchar_t * & end )
2010-11-22 02:23:32 +01:00
{
2014-10-11 21:56:48 +02:00
while ( start ! = end & & IsWhite ( * start ) )
2010-11-22 02:23:32 +01:00
+ + start ;
2014-10-11 21:56:48 +02:00
while ( start ! = end & & IsWhite ( * ( end - 1 ) ) )
2010-11-22 02:23:32 +01:00
- - end ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : SkipWhite ( const wchar_t * & str )
2010-11-22 02:23:32 +01:00
{
2014-10-11 21:56:48 +02:00
while ( IsWhite ( * str ) )
2010-11-22 02:23:32 +01:00
str + = 1 ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
size_t Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : StrToSize ( const wchar_t * str , const wchar_t * * str_end )
2010-11-22 02:23:32 +01:00
{
2012-02-24 13:04:36 +01:00
size_t res = 0 ;
2010-11-22 02:23:32 +01:00
SkipWhite ( str ) ;
2012-02-24 13:04:36 +01:00
// !! IMPROVE ME
2010-11-22 02:23:32 +01:00
// overflow is not checked
while ( * str > = ' 0 ' & & * str < = ' 9 ' )
{
res * = 10 ;
res + = * str - ' 0 ' ;
str + = 1 ;
}
SkipWhite ( str ) ;
2013-11-07 11:16:10 +01:00
if ( str_end )
* str_end = str ;
2010-11-22 02:23:32 +01:00
return res ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CopyTmpStreamToOutputStreams ( Item : : Function & fun , StreamType & ezc_out_tmp_stream , StreamType & previous_stream )
2011-01-26 13:42:49 +01:00
{
2021-05-28 16:10:16 +02:00
if ( output_frames_streams )
2013-11-07 11:16:10 +01:00
{
2021-06-20 16:54:55 +02:00
CopyStream ( ezc_out_tmp_stream , previous_stream ) ;
2015-11-12 10:53:20 +01:00
2021-06-20 16:54:55 +02:00
for ( size_t s = 0 ; s < fun . parameters . size ( ) ; + + s )
2013-11-07 11:16:10 +01:00
{
2021-06-20 16:54:55 +02:00
std : : wstring & name = fun . parameters [ s ] - > name ;
auto imap = output_frames_streams - > streams_map . find ( name ) ;
2013-11-07 11:16:10 +01:00
2021-06-20 16:54:55 +02:00
if ( imap = = output_frames_streams - > streams_map . end ( ) )
2015-11-12 10:53:20 +01:00
{
2021-06-20 16:54:55 +02:00
if ( output_frames_streams - > streams_map . size ( ) < output_frames_streams - > streams_tab . size ( ) )
2015-11-12 10:53:20 +01:00
{
2021-06-20 16:54:55 +02:00
/* 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 ) ;
2015-11-12 10:53:20 +01:00
}
else
{
2021-06-20 16:54:55 +02:00
CreateMsg ( L " limit of output streams in OutStreams<> has been reached " ) ;
2015-11-12 10:53:20 +01:00
}
}
2021-06-20 16:54:55 +02:00
else
{
StreamType * stream = imap - > second ;
CopyStream ( ezc_out_tmp_stream , * stream ) ;
}
2013-11-07 11:16:10 +01:00
}
}
2011-01-26 13:42:49 +01:00
}
2021-06-19 20:18:30 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CreateMsg ( const wchar_t * type , const wchar_t * arg )
2014-10-19 07:42:25 +02:00
{
2021-06-19 20:18:30 +02:00
if ( plog )
2014-10-19 07:42:25 +02:00
{
2021-06-20 16:54:55 +02:00
( * plog ) < < pt : : Log : : log2 < < " Ezc: " < < type ;
2014-10-19 07:42:25 +02:00
2021-06-19 20:18:30 +02:00
if ( arg )
{
2021-06-20 16:54:55 +02:00
( * plog ) < < ' ' < < arg ;
2021-06-19 20:18:30 +02:00
}
( * plog ) < < pt : : Log : : logend ;
}
2014-10-19 07:42:25 +02:00
}
2021-06-19 20:18:30 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CreateMsg ( const wchar_t * type , const std : : wstring & model_name , std : : vector < std : : wstring > & fields , size_t how_many_fields_print ,
2021-06-19 20:18:30 +02:00
const wchar_t * arg , const wchar_t * arg2 , const wchar_t * arg3 )
2015-11-12 10:53:20 +01:00
{
2021-06-19 20:18:30 +02:00
if ( plog )
{
( * plog ) < < pt : : Log : : log2 < < L " Ezc: " < < type < < model_name ;
2015-11-12 10:53:20 +01:00
2021-06-25 16:16:30 +02:00
for ( size_t i = 0 ; i < how_many_fields_print & & i < fields . size ( ) ; + + i )
2021-06-19 20:18:30 +02:00
{
2021-06-25 16:16:30 +02:00
( * plog ) < < ' . ' < < fields [ i ] ;
2021-06-19 20:18:30 +02:00
}
2010-11-22 02:23:32 +01:00
2021-06-19 20:18:30 +02:00
if ( arg )
{
( * plog ) < < arg ;
}
if ( arg2 )
{
( * plog ) < < arg2 ;
}
if ( arg3 )
{
( * plog ) < < arg3 ;
}
2010-11-22 02:23:32 +01:00
2021-06-19 20:18:30 +02:00
( * plog ) < < pt : : Log : : logend ;
}
}
2010-11-22 02:23:32 +01:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CreateMsg ( const wchar_t * type , const std : : wstring & model_name , std : : vector < std : : wstring > & fields ,
2021-06-25 16:16:30 +02:00
const wchar_t * arg , const wchar_t * arg2 , const wchar_t * arg3 )
{
CreateMsg ( type , model_name , fields , fields . size ( ) , arg , arg2 , arg3 ) ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CreateMsg ( const std : : wstring & type , const std : : wstring & arg )
2010-11-22 02:23:32 +01:00
{
2010-11-25 23:39:58 +01:00
CreateMsg ( type . c_str ( ) , arg . c_str ( ) ) ;
2010-11-22 02:23:32 +01:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : CreateMsg ( const std : : wstring & type )
2010-11-22 02:23:32 +01:00
{
2010-11-25 23:39:58 +01:00
CreateMsg ( type . c_str ( ) ) ;
2010-11-22 02:23:32 +01:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : EvaluateProgramNode ( Item & item )
2018-10-30 00:50:10 +01:00
{
if ( output_stream )
{
if ( item . type = = Item : : item_function )
2018-10-30 21:59:17 +01:00
* output_stream < < " expression: " < < item . text ;
2018-10-30 00:50:10 +01:00
if ( item . type = = Item : : item_if )
2018-10-30 21:59:17 +01:00
* output_stream < < " if: " < < item . text ;
2018-10-30 00:50:10 +01:00
if ( item . type = = Item : : item_for )
2018-10-30 21:59:17 +01:00
* output_stream < < " for: " < < item . text ;
2018-10-30 00:50:10 +01:00
}
last_res = false ;
if ( expression_parser )
{
if ( expression_parser - > Parse ( item . text ) )
{
last_res = expression_parser - > LastResultToBool ( ) ;
2018-10-30 21:59:17 +01:00
if ( output_stream )
{
* output_stream < < " -> " < < expression_parser - > LastResult ( ) ;
}
2018-10-30 00:50:10 +01:00
}
else
{
if ( output_stream )
{
2018-10-30 21:59:17 +01:00
* output_stream < < " -> syntax error when evaluating expression: error code: " < < ( int ) expression_parser - > LastError ( ) ;
2018-10-30 00:50:10 +01:00
}
}
}
2018-10-30 21:59:17 +01:00
if ( output_stream )
{
* output_stream < < " \n " ;
}
2018-10-30 00:50:10 +01:00
}
2010-11-22 02:23:32 +01:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : MakeItemText ( Item & item )
2010-11-22 02:23:32 +01:00
{
const wchar_t * start = item . text . c_str ( ) ;
const wchar_t * end = item . text . c_str ( ) + item . text . size ( ) ;
if ( trim_white )
TrimWhite ( start , end ) ;
if ( special_chars )
PrintSpecialText ( start , end ) ;
else
PrintNormalText ( start , end ) ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : MakeTextContainer ( Item & item )
2010-11-22 02:23:32 +01:00
{
std : : vector < Item * > : : iterator i = item . item_tab . begin ( ) ;
for ( ; i ! = item . item_tab . end ( ) & & ! break_generating ; + + i )
2011-07-15 04:09:40 +02:00
MakeText ( * * i ) ;
2010-11-22 02:23:32 +01:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : MakeTextFunction ( Item & item )
2010-11-22 02:23:32 +01:00
{
2012-02-24 13:04:36 +01:00
is_generating_normal = true ;
2013-11-07 11:16:10 +01:00
2018-10-30 00:50:10 +01:00
if ( program_mode )
2013-11-07 11:16:10 +01:00
{
2018-10-30 00:50:10 +01:00
EvaluateProgramNode ( item ) ;
2013-11-07 11:16:10 +01:00
}
else
{
2018-10-30 00:50:10 +01:00
if ( output_stream )
{
2021-05-23 10:02:51 +02:00
Call ( item . function , nullptr , * output_stream , false , empty_stream ) ;
2018-10-30 00:50:10 +01:00
}
else
{
2021-05-23 10:02:51 +02:00
Call ( item . function , nullptr , stream_temp1 , false , empty_stream ) ;
2018-10-30 00:50:10 +01:00
ClearStream ( stream_temp1 ) ;
}
2013-11-07 11:16:10 +01:00
}
2010-11-22 02:23:32 +01:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : MakeTextIf_go ( Item & item , bool result )
2010-11-22 02:23:32 +01:00
{
if ( result )
{
if ( item . item_tab . size ( ) > 0 )
MakeText ( * item . item_tab [ 0 ] ) ;
}
else
{
// second element can be (or not -- it's from [else])
if ( item . item_tab . size ( ) > 1 )
MakeText ( * item . item_tab [ 1 ] ) ;
}
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : MakeTextIf ( Item & item )
2010-11-22 02:23:32 +01:00
{
2012-02-24 13:04:36 +01:00
is_generating_if = true ;
2018-10-30 00:50:10 +01:00
if ( program_mode )
{
EvaluateProgramNode ( item ) ;
}
else
{
if ( ! Call ( item . function ) )
return ;
}
2010-11-22 02:23:32 +01:00
2011-04-26 19:17:06 +02:00
MakeTextIf_go ( item , last_res ) ;
2010-11-22 02:23:32 +01:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : MakeTextIfDef ( Item & item )
2021-07-02 20:23:20 +02:00
{
is_generating_if_def = true ;
if ( program_mode )
{
//CHECKME
//EvaluateProgramNode(item);
}
else
{
last_res = Call ( item . function ) ;
}
MakeTextIf_go ( item , last_res ) ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : MakeTextIfNotDef ( Item & item )
2021-07-02 20:23:20 +02:00
{
is_generating_if_not_def = true ;
if ( program_mode )
{
//CHECKME
//EvaluateProgramNode(item);
}
else
{
last_res = ! Call ( item . function ) ;
}
MakeTextIf_go ( item , last_res ) ;
}
2010-11-22 02:23:32 +01:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : MakeTextFor ( Item & item )
2010-11-22 02:23:32 +01:00
{
2012-03-03 21:58:55 +01:00
stack_tab [ stack_index - 1 ] . is_for = true ;
2012-02-27 18:39:46 +01:00
for ( ; ! break_generating ; stack_tab [ stack_index - 1 ] . iter + = 1 )
2010-11-22 02:23:32 +01:00
{
2012-02-27 18:39:46 +01:00
if ( stack_tab [ stack_index - 1 ] . iter > = max_for_items )
2010-11-22 02:23:32 +01:00
{
2015-03-08 03:31:21 +01:00
CreateMsg ( item . function . name . c_str ( ) ,
2010-11-22 02:23:32 +01:00
L " function exceeded a limit for a [for] statement " ) ;
break ;
}
2012-01-17 23:57:06 +01:00
// is_generating_for will be changed by next call to MakeText()
// so we should set it in each iterations
is_generating_for = true ;
2018-10-30 00:50:10 +01:00
if ( program_mode )
{
EvaluateProgramNode ( item ) ;
}
else
{
2021-05-23 10:02:51 +02:00
Call ( item . function , nullptr , stream_temp1 , true , empty_stream ) ;
2018-10-30 00:50:10 +01:00
}
2010-11-22 02:23:32 +01:00
2011-04-26 19:17:06 +02:00
if ( ! last_res )
2010-11-22 02:23:32 +01:00
break ;
if ( ! item . item_tab . empty ( ) )
2018-10-30 00:50:10 +01:00
MakeText ( * item . item_tab [ 0 ] ) ; // should be only one item
2010-11-22 02:23:32 +01:00
}
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : MakeTextDefine ( Item & item , Var & var )
2010-11-22 02:23:32 +01:00
{
2021-05-23 10:02:51 +02:00
var . str . clear ( ) ;
var . res = ConvertToBool ( var . str ) ;
var . is_function = false ;
if ( item . function . parameters . empty ( ) )
2010-11-25 23:39:58 +01:00
{
return ;
}
2015-03-08 03:31:21 +01:00
2021-05-23 10:02:51 +02:00
if ( item . function . parameters . size ( ) > 1 )
2010-11-22 02:23:32 +01:00
{
2021-05-23 10:02:51 +02:00
CreateMsg ( L " [def] can have only one parameter " ) ;
return ;
}
Item : : Function & fun = * item . function . parameters [ 0 ] ;
if ( fun . is_function )
{
// call function
if ( Call ( fun , nullptr , stream_temp_define , true , empty_stream ) )
2014-10-17 23:36:55 +02:00
{
2021-06-20 16:54:55 +02:00
CopyStreamToString ( stream_temp_define , var . str ) ;
2021-05-23 10:02:51 +02:00
var . res = last_res ;
2014-10-17 23:36:55 +02:00
}
else
{
2021-05-23 10:02:51 +02:00
CreateMsg ( L " [def] unknown function/block/variable " , item . function . name ) ;
2014-10-17 23:36:55 +02:00
}
2010-11-22 02:23:32 +01:00
}
2021-05-23 10:02:51 +02:00
else
{
var . str = fun . name ;
var . res = ConvertToBool ( fun . name ) ;
}
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : MakeTextDefine ( Item & item )
2021-05-23 10:02:51 +02:00
{
if ( ! can_use_vars | | ! pvars )
{
CreateMsg ( L " [def] statement not available " ) ;
return ;
}
Var & var = ( * pvars ) [ item . function . name ] ;
MakeTextDefine ( item , var ) ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : MakeTextDefineIfNotSet ( Item & item )
2021-05-23 10:02:51 +02:00
{
if ( ! can_use_vars | | ! pvars )
{
CreateMsg ( L " [def?] statement not available " ) ;
return ;
}
Vars : : iterator vi = pvars - > find ( item . function . name ) ;
if ( vi = = pvars - > end ( ) )
{
Var & var = ( * pvars ) [ item . function . name ] ;
MakeTextDefine ( item , var ) ;
}
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : MakeTextLet ( Item & item , Var & var )
2021-05-23 10:02:51 +02:00
{
var . str . clear ( ) ;
var . res = ConvertToBool ( var . str ) ;
var . is_function = true ;
if ( item . function . parameters . empty ( ) )
{
var . is_function = false ;
return ;
}
if ( item . function . parameters . size ( ) > 1 )
{
CreateMsg ( L " [let] can have only one parameter " ) ;
return ;
}
Item : : Function & fun = * item . function . parameters [ 0 ] ;
var . str = fun . name ;
var . is_function = fun . is_function ;
if ( ! fun . is_function )
{
var . res = ConvertToBool ( var . str ) ;
}
2010-11-22 02:23:32 +01:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : MakeTextLet ( Item & item )
2021-05-23 10:02:51 +02:00
{
if ( ! can_use_vars | | ! pvars )
{
CreateMsg ( L " [let] statement not available " ) ;
return ;
}
Var & var = ( * pvars ) [ item . function . name ] ;
MakeTextLet ( item , var ) ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : MakeTextLetIfNotSet ( Item & item )
2021-05-23 10:02:51 +02:00
{
if ( ! can_use_vars | | ! pvars )
{
CreateMsg ( L " [let?] statement not available " ) ;
return ;
}
Vars : : iterator vi = pvars - > find ( item . function . name ) ;
if ( vi = = pvars - > end ( ) )
{
Var & var = ( * pvars ) [ item . function . name ] ;
MakeTextLet ( item , var ) ;
}
}
2010-11-22 02:23:32 +01:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : MakeTextFilter ( Item & item )
2011-01-26 13:42:49 +01:00
{
if ( filter_index > = filter_tab . size ( ) )
{
CreateMsg ( L " Generator exceeded allowed number of filters " ) ;
return ;
}
2013-11-07 11:16:10 +01:00
2011-01-26 13:42:49 +01:00
StreamType * old_stream = output_stream ;
output_stream = filter_tab [ filter_index ] ;
ClearStream ( * output_stream ) ;
filter_index + = 1 ;
if ( ! item . item_tab . empty ( ) )
MakeText ( * item . item_tab [ 0 ] ) ; // should be only one item - item_container
2012-02-24 13:04:36 +01:00
is_generating_filter = true ;
2011-01-26 13:42:49 +01:00
2013-11-07 11:16:10 +01:00
if ( old_stream )
{
2021-05-23 10:02:51 +02:00
Call ( item . function , nullptr , * old_stream , false , * output_stream ) ;
2013-11-07 11:16:10 +01:00
}
else
{
2021-05-23 10:02:51 +02:00
Call ( item . function , nullptr , stream_temp1 , true , * output_stream ) ;
2013-11-07 11:16:10 +01:00
ClearStream ( stream_temp1 ) ;
}
ClearStream ( * output_stream ) ;
2011-01-26 13:42:49 +01:00
output_stream = old_stream ;
filter_index - = 1 ;
}
2013-11-07 11:16:10 +01:00
2015-11-12 10:53:20 +01:00
/*
2021-05-28 16:10:16 +02:00
although we are using a stack for [ etc frame ] there is no need for the stack now
2015-11-12 10:53:20 +01:00
because the output is only a one - level map ( not nested structure )
2021-05-20 16:12:41 +02:00
but in the future we can use more complicated class like pt : : Space
2021-05-28 16:10:16 +02:00
and then nested [ ezc frame ] statements can product a better output
2015-11-12 10:53:20 +01:00
*/
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : MakeEzcFrame ( Item & item )
2013-11-07 11:16:10 +01:00
{
2015-11-12 10:53:20 +01:00
std : : vector < std : : wstring * > output_stream_names ;
StreamType * old_stream ;
bool stream_added = true ;
2013-11-07 11:16:10 +01:00
2021-05-28 16:10:16 +02:00
if ( ezc_frames_stack_index > = ezc_frame_stack_tab . size ( ) )
2013-11-07 11:16:10 +01:00
{
2021-05-28 16:10:16 +02:00
CreateMsg ( L " Generator exceeded allowed number of [ezc frame] statements " ) ;
2015-11-12 10:53:20 +01:00
return ;
2013-11-07 11:16:10 +01:00
}
2015-11-12 10:53:20 +01:00
/*
2021-05-28 16:10:16 +02:00
if we encounter the first ezc frame statement without arguments e . g . [ ezc frame ] or just [ frame ]
2015-11-12 10:53:20 +01:00
then we can simply ignore it
*/
2021-05-28 16:10:16 +02:00
if ( item . function . parameters . empty ( ) & & ezc_frames_stack_index = = 0 )
2015-11-12 10:53:20 +01:00
stream_added = false ;
if ( stream_added )
2013-11-07 11:16:10 +01:00
{
2015-11-12 10:53:20 +01:00
old_stream = output_stream ;
2021-05-28 16:10:16 +02:00
output_stream = ezc_frame_stack_tab [ ezc_frames_stack_index ] ;
2015-11-12 10:53:20 +01:00
ClearStream ( * output_stream ) ;
2021-05-28 16:10:16 +02:00
ezc_frames_stack_index + = 1 ;
2013-11-07 11:16:10 +01:00
}
2015-11-12 10:53:20 +01:00
if ( ! item . item_tab . empty ( ) )
MakeText ( * item . item_tab [ 0 ] ) ; // should be only one item - item_container
if ( stream_added )
2013-11-07 11:16:10 +01:00
{
2015-11-12 10:53:20 +01:00
CopyTmpStreamToOutputStreams ( item . function , * output_stream , * old_stream ) ;
ClearStream ( * output_stream ) ;
output_stream = old_stream ;
2021-05-28 16:10:16 +02:00
ezc_frames_stack_index - = 1 ;
2013-11-07 11:16:10 +01:00
}
}
2015-11-12 10:53:20 +01:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : MakeTextEzc ( Item & item )
2013-11-07 11:16:10 +01:00
{
2021-05-28 16:10:16 +02:00
if ( item . function . name = = L " frame " )
2021-06-29 23:38:38 +02:00
{
2021-05-28 16:10:16 +02:00
MakeEzcFrame ( item ) ;
2021-06-29 23:38:38 +02:00
}
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 ) ;
}
2013-11-07 11:16:10 +01:00
2015-03-08 03:31:21 +01:00
// in the future we can use more builtin functions
2013-11-07 11:16:10 +01:00
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : MakeTextReturn ( Item & item )
2014-10-28 18:46:24 +01:00
{
last_res = false ;
if ( block_stack_index = = 0 )
{
// the [return] statement is not called from a [block]
CreateMsg ( L " [return] should be called from a [block] " ) ;
return ;
}
BlockStack & block_stack = block_stack_tab [ block_stack_index - 1 ] ;
block_stack . was_return = true ;
2015-03-08 03:31:21 +01:00
if ( item . has_function )
2014-10-28 18:46:24 +01:00
{
2015-03-08 03:31:21 +01:00
// output stream in [return] statement is ignored (we use only the stream produced by the whole block)
2014-10-28 18:46:24 +01:00
// this Call() sets last_res which is used later when we return to CallBlock()
2021-05-23 10:02:51 +02:00
Call ( item . function , nullptr , stream_temp1 , false , empty_stream ) ;
2014-10-28 18:46:24 +01:00
ClearStream ( stream_temp1 ) ;
}
}
2013-11-07 11:16:10 +01:00
2014-10-17 23:36:55 +02:00
2021-05-23 10:02:51 +02:00
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : LimitAchieved ( )
2010-11-22 02:23:32 +01:00
{
if ( break_generating )
2012-02-27 18:39:46 +01:00
return true ;
2014-10-28 18:46:24 +01:00
if ( current_item > = max_items )
2010-11-22 02:23:32 +01:00
{
break_generating = true ;
2010-11-25 23:39:58 +01:00
CreateMsg ( L " Generator exceeded allowed number of elements " ) ;
2012-02-27 18:39:46 +01:00
return true ;
2010-11-22 02:23:32 +01:00
}
2014-10-28 18:46:24 +01:00
if ( stack_index > = stack_tab . size ( ) )
2012-02-27 18:39:46 +01:00
{
break_generating = true ;
CreateMsg ( L " Generator exceeded the stack size " ) ;
return true ;
}
2014-10-28 18:46:24 +01:00
if ( block_stack_index > 0 )
{
BlockStack & block_stack = block_stack_tab [ block_stack_index - 1 ] ;
if ( block_stack . was_return )
return true ;
}
2012-02-27 18:39:46 +01:00
return false ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream > : : MakeText ( Item & item )
2012-02-27 18:39:46 +01:00
{
if ( LimitAchieved ( ) )
return ;
2021-07-02 20:23:20 +02:00
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 ;
2012-01-17 23:57:06 +01:00
2012-02-27 18:39:46 +01:00
stack_tab [ stack_index - 1 ] . Clear ( ) ;
2016-04-04 17:53:11 +02:00
stack_tab [ stack_index - 1 ] . item = & item ;
2012-02-27 18:39:46 +01:00
2021-05-23 10:02:51 +02:00
if ( item . type = = Item : : item_text ) MakeItemText ( item ) ;
else if ( item . type = = Item : : item_container ) MakeTextContainer ( item ) ;
2021-06-20 16:54:55 +02:00
else if ( item . type = = Item : : item_function ) MakeTextFunction ( item ) ;
2021-05-23 10:02:51 +02:00
else if ( item . type = = Item : : item_if ) MakeTextIf ( item ) ;
2021-07-02 20:23:20 +02:00
else if ( item . type = = Item : : item_if_def ) MakeTextIfDef ( item ) ;
else if ( item . type = = Item : : item_if_not_def ) MakeTextIfNotDef ( item ) ;
2021-05-23 10:02:51 +02:00
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 ) ;
else if ( item . type = = Item : : item_let_if_not_set ) MakeTextLetIfNotSet ( item ) ;
else if ( item . type = = Item : : item_for ) MakeTextFor ( item ) ;
else if ( item . type = = Item : : item_filter ) MakeTextFilter ( item ) ;
else if ( item . type = = Item : : item_ezc ) MakeTextEzc ( item ) ;
else if ( item . type = = Item : : item_return ) MakeTextReturn ( item ) ;
2010-11-22 02:23:32 +01:00
else if ( item . type = = Item : : item_err )
2010-11-25 23:39:58 +01:00
CreateMsg ( L " a wrong directive " ) ;
2012-02-27 18:39:46 +01:00
RemoveStackFunData ( stack_tab [ stack_index - 1 ] ) ;
stack_index - = 1 ;
2010-11-22 02:23:32 +01:00
}
} // namespace Ezc
# endif
2014-11-02 18:26:56 +01:00