2010-11-22 01:23:32 +00:00
/*
2014-10-17 21:48:11 +00:00
* This file is a part of EZC -- Easy templating in C++ library
2022-07-03 08:52:24 +02:00
* and is distributed under the 2-Clause BSD licence.
2010-11-22 01:23:32 +00:00
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
2024-07-07 21:55:49 +02:00
* Copyright (c) 2007-2024, Tomasz Sowa
2010-11-22 01:23:32 +00: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:
2022-07-03 08:52:24 +02:00
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. 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.
2010-11-22 01:23:32 +00:00
*
* 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
2022-07-03 08:52:24 +02:00
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
2010-11-22 01:23:32 +00:00
* 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)
2022-07-03 08:52:24 +02:00
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
2010-11-22 01:23:32 +00:00
*/
#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 21:36:55 +00:00
#include "blocks.h"
2010-11-22 01:23:32 +00:00
#include "pattern.h"
#include "functions.h"
2015-06-14 18:20:00 +00:00
#include "objects.h"
2015-11-12 09:53:20 +00:00
#include "outstreams.h"
2018-10-29 23:50:10 +00: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 12:42:49 +00:00
2021-06-16 14:16:49 +02:00
#ifdef EZC_HAS_MORM_LIBRARY
#include "model.h"
#endif
2010-11-22 01:23:32 +00:00
namespace Ezc
{
2012-02-27 17:39:46 +00:00
2010-11-25 01:55:32 +00:00
/*
StreamType
2010-11-25 22:39:58 +00:00
we use only method write(const wchar_t * str, size_t len) from the stream
2010-11-25 01:55:32 +00: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 01:23:32 +00:00
class Generator
{
public :
Generator ();
2011-01-26 12:42:49 +00:00
Generator ( const Generator & n );
Generator & operator = ( const Generator & n );
~ Generator ();
2014-10-17 21:36:55 +00:00
void SetPattern ( Pattern & pattern );
void SetBlocks ( Blocks & blocks );
void SetFunctions ( Functions < StreamType > & functions );
2015-06-14 18:20:00 +00: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 01:23:32 +00:00
2012-02-24 12:04:36 +00:00
void SetMax ( size_t max_items_ , size_t max_for_items_ );
2010-11-22 01:23:32 +00: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 01:55:32 +00:00
// if the second character is different from those shown above the first slash will be printed
// so "\x" gives "\x"
2010-11-22 01:23:32 +00: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 12:42:49 +00:00
// default: 20
void SetMaxFilters ( size_t new_len );
2012-02-27 17:39:46 +00:00
// default stack size: 300
void SetStackSize ( size_t new_stack_size );
2014-10-19 21:09:34 +00: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-29 23:50:10 +00:00
void SetProgramMode ( bool program_mode );
void SetExpressionParser ( ExpressionParser * expression_parser );
2024-07-07 21:55:49 +02:00
// some optimization when generating the output
// if provided frames then only such frames will be generated
// call OnlyFrames(nullptr) to disable it (default)
void OnlyFrames ( const std :: vector < std :: wstring > & frames );
void OnlyFrames ( const std :: vector < std :: wstring > * frames );
// some optimization when generating the output
// whether or not the main stream should be produced (true by default)
void UseMainStream ( bool use_main_stream );
2018-10-29 23:50:10 +00:00
2010-11-25 22:39:58 +00:00
// the main methods for generating
2015-11-12 09:53:20 +00: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 09:53:20 +00:00
2010-11-25 22:39:58 +00:00
2010-11-22 01:23:32 +00:00
private :
2014-10-28 17:46:24 +00: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 21:36:55 +00:00
struct BlockStack
{
2014-10-28 17:46:24 +00:00
std :: vector < Var > args ;
2014-10-17 21:36:55 +00:00
StreamType * out_stream ;
2014-10-28 17:46:24 +00:00
bool was_return ;
2014-10-17 21:36:55 +00:00
};
std :: vector < BlockStack > block_stack_tab ;
size_t block_stack_index ;
size_t block_stack_size ;
2015-11-12 09:53:20 +00: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 01:23:32 +00:00
StreamType * output_stream ;
2014-10-17 21:36:55 +00:00
Pattern * ppattern ;
Blocks * pblocks ;
Functions < StreamType > * pfunctions ;
2015-06-14 18:20:00 +00: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 10:16:10 +00:00
2015-11-12 09:53:20 +00: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 10:16:10 +00:00
2010-11-22 01:23:32 +00:00
// temporary error messages
std :: wstring temp_msg ;
bool break_generating ;
2012-02-24 12:04:36 +00:00
size_t current_item ;
size_t max_items ;
size_t max_for_items ;
2010-11-22 01:23:32 +00:00
bool special_chars ;
bool trim_white ;
bool skip_new_line ;
2012-02-27 17:39:46 +00:00
2021-05-28 16:10:16 +02:00
size_t ezc_frames_stack_index ;
size_t ezc_frames_stack_size ;
2015-11-12 09:53:20 +00:00
2012-02-27 17:39:46 +00:00
size_t stack_index ;
size_t stack_size ;
2011-01-26 12:42:49 +00: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 12:42:49 +00:00
const StreamType empty_stream ;
2014-11-02 17:26:56 +00:00
// temporary streams used in [if..] [for...] or [def ...]
2013-11-07 10:16:10 +00:00
// or if output_stream is null and an ezc function should be called
2014-11-02 17:26:56 +00:00
StreamType stream_temp1 , stream_temp_define ;
2011-01-26 12:42:49 +00:00
2011-04-26 17:17:06 +00:00
// last result from a user function (FunInfo::res)
bool last_res ;
2010-11-22 01:23:32 +00:00
2011-04-26 17:17:06 +00:00
// true if this Generator is working now
bool is_generator_working ;
2012-02-24 12:04:36 +00:00
// true if the Generator is working with [for ...], [if ...] etc.
2012-01-17 22:57:06 +00:00
bool is_generating_for ;
2012-02-24 12:04:36 +00: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 12:04:36 +00:00
bool is_generating_normal ;
bool is_generating_filter ;
2012-01-17 22:57:06 +00:00
2011-04-26 17:17:06 +00:00
// an empty string for FunInfo objects
2010-11-22 01:23:32 +00:00
// when there is no any parameters
const std :: wstring empty ;
2011-04-26 17:17:06 +00:00
// a stack for [for] statements
2012-02-27 17:39:46 +00:00
std :: vector < Stack > stack_tab ;
2011-01-14 23:59:30 +00:00
2014-10-19 21:09:34 +00:00
bool can_use_vars ;
bool can_find_in_cache ;
2018-10-29 23:50:10 +00:00
bool program_mode ;
2024-07-07 21:55:49 +02:00
const std :: vector < std :: wstring > * only_frames ;
bool is_output_stream_allowed ;
bool use_main_stream ;
2018-10-29 23:50:10 +00:00
ExpressionParser * expression_parser ;
2015-11-12 09:53:20 +00:00
void ResizeStreamStack ( std :: vector < StreamType *> & stream_tab , size_t stream_tab_max_size );
2011-01-26 12:42:49 +00:00
void ResizeFilterTab ();
2012-02-27 17:39:46 +00:00
void ResizeStack ();
2014-10-17 21:36:55 +00:00
void ResizeBlockStack ();
2021-05-28 16:10:16 +02:00
void ResizeEzcFrameStack ();
2014-10-17 21:36:55 +00:00
2015-11-12 09:53:20 +00:00
void ClearStreamStack ( std :: vector < StreamType *> & stream_tab );
2011-01-26 12:42:49 +00:00
void ClearFilterTab ();
2014-10-17 21:36:55 +00:00
void ClearForStack ();
2014-10-21 07:21:20 +00:00
void ClearBlockStack ();
2021-05-28 16:10:16 +02:00
void ClearEzcFrameTab ();
2014-10-21 07:21:20 +00:00
2011-01-26 12:42:49 +00: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 17:39:46 +00:00
void RemoveStackFunData ( Stack & sitem );
2011-01-26 12:42:49 +00:00
2015-03-08 02:31:21 +00:00
bool ConvertToBool ( const std :: wstring & str );
2011-04-26 17:17:06 +00:00
template < class CharType >
CharType ToLower ( CharType c );
2021-07-02 20:23:20 +02:00
bool IsTestingFunctionExistence ();
2015-06-14 18:20:00 +00:00
2021-06-16 14:16:49 +02:00
bool CheckBlockArgument ( int arg_index , FindHelper & find_helper );
2015-06-14 18:20:00 +00:00
2021-06-16 14:16:49 +02:00
bool FindInCache ( Item :: Function & item_fun , FindHelper & find_helper );
2011-04-26 17:17:06 +00: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 12:42:49 +00: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 21:36:55 +00:00
2021-06-16 14:16:49 +02:00
void CallFunction ( typename Functions < StreamType >:: UserFunction & function ,
2014-10-28 17:46:24 +00:00
std :: vector < Var > & parameters ,
StreamType & out_stream ,
const StreamType & in_stream );
2014-10-17 21:36:55 +00:00
bool CallBlock ( Item & item_block ,
2014-10-28 17:46:24 +00:00
std :: vector < Var > & parameters ,
2014-10-17 21:36:55 +00: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 18:20:00 +00:00
2021-08-17 17:33:51 +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-01 23:21:20 +02:00
2021-08-17 17:33:51 +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-08-17 17:33:51 +02:00
bool CallModelField ( morm :: Model & model , const std :: wstring & field , std :: vector < Var > & parameters , StreamType & out_stream , const StreamType & in_stream );
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-08-17 17:33:51 +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 18:20:00 +00:00
2021-06-16 14:16:49 +02:00
void CallObject ( BaseObj < StreamType > & base_obj ,
2015-06-14 18:20:00 +00: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 18:20:00 +00:00
2014-10-17 21:36:55 +00:00
bool Call ( Item :: Function & item_fun ,
2021-05-23 10:02:51 +02:00
std :: wstring * fun_name ,
2014-10-17 21:36:55 +00:00
StreamType & out_stream ,
bool clear_out_stream ,
const StreamType & in_stream );
bool Call ( Item :: Function & item_fun );
2011-01-26 12:42:49 +00:00
2010-11-22 01:23:32 +00:00
wchar_t CreateSpecialChar ( wchar_t c );
2010-11-25 01:55:32 +00:00
const wchar_t * PrintSpecialChar ( const wchar_t * start , const wchar_t * end );
2010-11-22 01:23:32 +00:00
void PrintSpecialText ( const wchar_t * start , const wchar_t * end );
void PrintNormalText ( const wchar_t * start , const wchar_t * end );
2014-10-11 19:56:48 +00:00
bool IsWhite ( wchar_t c );
2010-11-22 01:23:32 +00:00
void TrimWhite ( const wchar_t *& start , const wchar_t *& end );
void SkipWhite ( const wchar_t *& str );
2013-11-07 10:16:10 +00: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
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 01:23:32 +00:00
2024-07-07 21:55:49 +02:00
StreamType * FindAddOutputStream ( const std :: wstring & name );
void CopyTmpStreamToOutputStreams ( Item :: Function & fun , StreamType & ezc_out_tmp_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 22:39:58 +00: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 17:39:46 +00:00
bool LimitAchieved ();
2010-11-22 01:23:32 +00:00
2018-10-29 23:50:10 +00:00
void EvaluateProgramNode ( Item & item );
2024-07-07 21:55:49 +02:00
bool HasAskForSuchFrame ( Item :: Function & fun );
bool HasAskForSuchFrame ( const std :: wstring & name );
StreamType * GetNewStreamForFrame ();
void DecrementFramesStackIndex ();
2018-10-29 23:50:10 +00:00
2010-11-22 01:23:32 +00: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 01:23:32 +00: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 01:23:32 +00: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 12:42:49 +00:00
void MakeTextFilter ( Item & item );
2013-11-07 10:16:10 +00:00
void MakeTextEzc ( Item & item );
2014-10-28 17:46:24 +00:00
void MakeTextReturn ( Item & item );
2010-11-22 01:23:32 +00:00
void MakeText ( Item & item );
2024-07-07 21:55:49 +02:00
void MakeEzcFrame2 ( Item & item );
2021-05-28 16:10:16 +02:00
void MakeEzcFrame ( Item & item );
2013-11-07 10:16:10 +00:00
2014-10-17 21:36:55 +00:00
void Generate ();
2013-11-07 10:16:10 +00:00
2011-01-26 12:42:49 +00:00
2010-11-22 01:23:32 +00: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 01:23:32 +00: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 01:23:32 +00:00
max_items = 50000 ;
max_for_items = 5000 ;
2011-01-26 12:42:49 +00:00
filter_size = 20 ;
2010-11-22 01:23:32 +00:00
special_chars = false ;
trim_white = false ;
skip_new_line = false ;
2011-04-26 17:17:06 +00:00
is_generator_working = false ;
2012-02-27 17:39:46 +00:00
stack_size = 300 ;
2014-10-17 21:36:55 +00:00
block_stack_size = 64 ;
2021-05-28 16:10:16 +02:00
ezc_frames_stack_size = 16 ;
2014-10-19 21:09:34 +00:00
can_find_in_cache = true ;
can_use_vars = true ;
2018-10-29 23:50:10 +00:00
expression_parser = nullptr ;
2018-11-01 21:52:33 +00:00
program_mode = false ;
2024-07-07 21:55:49 +02:00
only_frames = nullptr ;
is_output_stream_allowed = true ;
use_main_stream = true ;
2010-11-22 01:23:32 +00: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 12:42:49 +00: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 12:42:49 +00:00
{
2014-10-17 21:36:55 +00:00
ppattern = n . ppattern ;
pblocks = n . pblocks ;
pfunctions = n . pfunctions ;
2015-06-14 18:20:00 +00: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 21:36:55 +00:00
2012-02-27 17:39:46 +00: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 21:09:34 +00:00
can_find_in_cache = n . can_find_in_cache ;
can_use_vars = n . can_use_vars ;
2012-02-27 17:39:46 +00:00
2014-10-17 21:36:55 +00: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 ;
2024-07-07 21:55:49 +02:00
expression_parser = n . expression_parser ;
2018-11-01 21:52:33 +00:00
program_mode = n . program_mode ;
2024-07-07 21:55:49 +02:00
only_frames = n . only_frames ;
is_output_stream_allowed = n . is_output_stream_allowed ;
use_main_stream = n . use_main_stream ;
2014-10-17 21:36:55 +00:00
2014-10-19 21:09:34 +00:00
// vars doesn't have to be copied
2011-01-26 12:42:49 +00:00
// don't copy filter tab
2012-02-27 17:39:46 +00: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 12:42:49 +00:00
2012-02-25 03:29:44 +00:00
// !! CHECK ME
// may copying should be denied when generator is working?
2011-04-26 17:17:06 +00:00
// don't copy 'is_generator_working' flag
is_generator_working = false ;
2011-01-26 12:42:49 +00: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 12:42:49 +00:00
{
ClearFilterTab ();
2012-02-24 12:04:36 +00:00
ClearForStack ();
2014-10-21 07:21:20 +00:00
ClearBlockStack ();
2021-05-28 16:10:16 +02:00
ClearEzcFrameTab ();
2011-01-26 12:42:49 +00:00
}
2014-10-19 05:42:25 +00: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 21:36:55 +00: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 21:36:55 +00: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 21:36:55 +00: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 18:20:00 +00: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 21:09:34 +00: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 21:09:34 +00: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-29 23:50:10 +00: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-29 23:50:10 +00:00
{
this -> expression_parser = expression_parser ;
}
2014-10-19 21:09:34 +00:00
2024-07-07 21:55:49 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream >:: OnlyFrames ( const std :: vector < std :: wstring > & frames )
{
this -> only_frames = & frames ;
}
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream >:: OnlyFrames ( const std :: vector < std :: wstring > * frames )
{
this -> only_frames = frames ;
}
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream >:: UseMainStream ( bool use_main_stream )
{
this -> use_main_stream = use_main_stream ;
}
2014-10-17 21:36:55 +00:00
2011-01-26 12:42:49 +00: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 ()
2012-02-27 17:39:46 +00:00
{
if ( stack_tab . size () != stack_size )
{
if ( stack_tab . size () > stack_size )
{
for ( size_t i = stack_size ; i < stack_tab . size () ; ++ i )
RemoveStackFunData ( stack_tab [ i ]);
}
stack_tab . resize ( stack_size );
}
}
2015-11-12 09:53:20 +00: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 >:: ResizeStreamStack ( std :: vector < StreamType *> & stream_tab , size_t stream_tab_max_size )
2015-11-12 09:53:20 +00: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 ();
}
else
{
for ( size_t i = stream_tab_max_size ; i < stream_tab . size () ; ++ i )
delete stream_tab [ i ];
stream_tab . resize ( stream_tab_max_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 >:: ResizeFilterTab ()
2015-11-12 09:53:20 +00:00
{
ResizeStreamStack ( filter_tab , filter_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 >:: ResizeEzcFrameStack ()
2015-11-12 09:53:20 +00:00
{
2021-05-28 16:10:16 +02:00
ResizeStreamStack ( ezc_frame_stack_tab , ezc_frames_stack_size );
2015-11-12 09:53:20 +00: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 21:36:55 +00: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 09:53:20 +00: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 09:53:20 +00: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 12:42:49 +00:00
{
2015-11-12 09:53:20 +00: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 09:53:20 +00:00
{
2021-05-28 16:10:16 +02:00
ClearStreamStack ( ezc_frame_stack_tab );
2011-01-26 12:42:49 +00: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 07:21:20 +00: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 12:04:36 +00:00
{
for ( size_t i = 0 ; i < stack_tab . size () ; ++ i )
2012-02-25 03:29:44 +00:00
RemoveStackFunData ( stack_tab [ i ]);
2012-02-24 12:04:36 +00: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 12:42:49 +00: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 12:42:49 +00:00
str . str ( L "" );
2021-07-12 23:00:11 +02:00
}
2011-01-26 12:42:49 +00:00
}
2010-11-22 01:23:32 +00: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
{
2021-07-12 23:00:11 +02:00
dst_stream << src_stream ;
2021-06-20 16:54:55 +02:00
}
else
{
2021-07-12 23:00:11 +02:00
dst_stream << src_stream . 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 >:: CopyStream ( pt :: WTextStream & src_stream , StreamType & dst_stream , bool should_escape )
{
if constexpr ( is_autoescape_stream )
{
dst_stream . Escape ( should_escape );
dst_stream << src_stream ;
}
else
{
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 03:29:44 +00:00
{
2014-10-19 05:42:25 +00:00
if ( s . fun_data && s . auto_remove )
2012-02-25 03:29:44 +00:00
{
2012-02-27 17:39:46 +00:00
delete s . fun_data ;
s . fun_data = 0 ;
2012-02-25 03:29:44 +00:00
}
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
2011-04-26 17:17:06 +00: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 17:17:06 +00: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 02:31:21 +00:00
{
2021-05-23 10:02:51 +02:00
return ! str . empty ();
2015-03-08 02:31:21 +00:00
}
2011-04-26 17:17:06 +00: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 01:23:32 +00: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 01:23:32 +00: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 01:23:32 +00: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 01:23:32 +00: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 )
2010-11-22 01:23:32 +00:00
{
2011-01-26 12:42:49 +00: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 17:39:46 +00:00
{
// the stack will be resized when Generate() method is called
stack_size = new_stack_size ;
}
2013-11-07 10:16:10 +00: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 ()
2011-01-26 12:42:49 +00:00
{
2011-04-26 17:17:06 +00:00
if ( is_generator_working )
2011-01-26 12:42:49 +00:00
{
2013-11-07 10:16:10 +00:00
CreateMsg ( L "generator busy" );
2011-01-26 12:42:49 +00:00
return ;
}
2010-11-25 22:39:58 +00:00
break_generating = false ;
current_item = 0 ;
2012-02-27 17:39:46 +00: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 21:36:55 +00:00
ClearForStack ();
2012-02-27 17:39:46 +00:00
2011-01-26 12:42:49 +00:00
ResizeFilterTab ();
2012-02-27 17:39:46 +00:00
ResizeStack ();
2014-10-17 21:36:55 +00:00
ResizeBlockStack ();
2021-05-28 16:10:16 +02:00
ResizeEzcFrameStack ();
2011-01-26 12:42:49 +00:00
filter_index = 0 ;
2012-02-27 17:39:46 +00:00
stack_index = 0 ;
2021-07-06 23:56:29 +02:00
ezc_frames_stack_index = 0 ;
2024-07-07 21:55:49 +02:00
is_output_stream_allowed = use_main_stream ;
2014-10-17 21:36:55 +00:00
block_stack_index = 0 ;
2010-11-25 22:39:58 +00:00
2014-10-17 21:36:55 +00:00
if ( ppattern )
2011-01-26 12:42:49 +00:00
{
try
{
2011-04-26 17:17:06 +00:00
is_generator_working = true ;
2014-10-17 21:36:55 +00:00
MakeText ( ppattern -> item_root );
2015-11-12 09:53:20 +00:00
// !! IMPROVE ME we can print an error message if the stacks are not empty
// (some [end] statements has been omited)
2011-04-26 17:17:06 +00:00
is_generator_working = false ;
2011-01-26 12:42:49 +00:00
}
catch (...)
{
2011-04-26 17:17:06 +00:00
is_generator_working = false ;
2011-01-26 12:42:49 +00:00
throw ;
}
}
2010-11-25 22:39:58 +00: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 )
2011-01-26 12:42:49 +00:00
{
2015-11-12 09:53:20 +00:00
output_stream = & out ;
2021-07-12 23:00:11 +02:00
output_frames_streams = nullptr ;
2014-10-17 21:36:55 +00:00
Generate ();
2011-01-26 12:42:49 +00: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 10:16:10 +00:00
{
2015-11-12 09:53:20 +00:00
output_stream = & out ;
2021-05-28 16:10:16 +02:00
output_frames_streams = & out_streams ;
2014-10-17 21:36:55 +00:00
Generate ();
2013-11-07 10:16:10 +00: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 10:16:10 +00: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 21:36:55 +00:00
Generate ();
2013-11-07 10:16:10 +00: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 18:20:00 +00: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 )
2013-11-07 10:16:10 +00:00
{
2021-05-23 10:02:51 +02:00
if ( arg_index < 0 )
2015-06-14 18:20:00 +00:00
return false ;
// it's a numeric function -- an argument to a block e.g.: [1]
if ( block_stack_index > 0 )
2010-11-22 01:23:32 +00:00
{
2015-06-14 18:20:00 +00:00
BlockStack & block_stack = block_stack_tab [ block_stack_index - 1 ];
2014-10-17 21:36:55 +00:00
2021-05-23 10:02:51 +02:00
if ( size_t ( arg_index ) < block_stack . args . size () )
2010-11-25 22:39:58 +00: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 21:36:55 +00:00
}
}
2021-05-23 10:02:51 +02:00
return false ;
2015-06-14 18:20:00 +00: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 18:20:00 +00:00
{
2014-10-19 21:09:34 +00:00
if ( can_find_in_cache )
2014-10-17 21:36:55 +00:00
{
2015-06-14 18:20:00 +00: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 18:20:00 +00:00
return true ;
}
2014-10-19 21:09:34 +00: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 21:09:34 +00:00
return true ;
}
2014-10-17 21:36:55 +00:00
2014-10-19 21:09:34 +00: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 21:09:34 +00:00
return true ;
}
2014-10-17 21:36:55 +00:00
}
return false ;
}
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 )
2014-10-17 21:36:55 +00:00
{
2015-06-14 18:20:00 +00: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 18:20:00 +00:00
if ( i != pobjects -> End () )
{
2021-06-16 14:16:49 +02:00
find_helper . base_obj = * i ;
2015-06-14 18:20:00 +00:00
return true ;
}
}
2014-10-17 21:36:55 +00:00
if ( pfunctions )
{
2014-10-17 22:14:28 +00:00
typename Functions < StreamType >:: Iterator i = pfunctions -> Find ( name );
2014-10-17 21:36:55 +00:00
if ( i != pfunctions -> End () )
{
2021-06-16 14:16:49 +02:00
find_helper . function = & i -> second ;
2010-11-25 22:39:58 +00:00
return true ;
}
2014-10-17 21:36:55 +00:00
}
if ( pblocks )
{
Blocks :: Iterator i = pblocks -> Find ( name );
if ( i != pblocks -> End () )
2010-11-25 22:39:58 +00:00
{
2021-06-16 14:16:49 +02:00
find_helper . item_block = & i -> second ;
2014-10-17 21:36:55 +00:00
return true ;
2010-11-25 22:39:58 +00:00
}
}
2014-10-17 21:36:55 +00:00
return false ;
}
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 )
2014-10-17 21:36:55 +00:00
{
2021-05-23 10:02:51 +02:00
if ( pvars )
2010-11-25 22:39:58 +00:00
{
2021-05-23 10:02:51 +02:00
Vars :: iterator i = pvars -> find ( name );
2014-10-17 21:36:55 +00: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-22 01:23:32 +00:00
}
2014-10-17 21:36:55 +00:00
2021-05-23 10:02:51 +02:00
return false ;
2014-10-17 21:36:55 +00: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 )
2014-10-17 21:36:55 +00:00
{
2021-08-14 17:44:11 +02:00
if ( CheckBlockArgument ( item_fun . arg , find_helper ) )
return true ;
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
2014-10-17 21:36:55 +00:00
2021-06-16 14:16:49 +02:00
if ( FindInCache ( item_fun , find_helper ) )
2015-06-14 18:20:00 +00:00
return true ;
2021-06-19 20:18:30 +02:00
if ( FindInFunctionsAndBlocks ( * find_helper . fun_name , find_helper ) )
2014-10-17 21:36:55 +00:00
return true ;
2021-06-19 20:18:30 +02:00
if ( FindInVariables ( * find_helper . fun_name , find_helper ) )
2014-10-17 21:36:55 +00:00
return true ;
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 01:23:32 +00: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 )
2021-07-02 20:23:20 +02:00
{
info . Clear ();
info . is_for = is_generating_for ;
info . is_if = is_generating_if ;
info . is_if_def = is_generating_if_def ;
info . is_if_not_def = is_generating_if_not_def ;
info . is_normal = is_generating_normal ;
info . is_filter = is_generating_filter ;
info . iter = info . stack . iter ;
info . stack_tab = stack_tab . data ();
info . stack_index = stack_index - 1 ;
}
2012-02-27 17:39:46 +00: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 )
2010-11-22 01:23:32 +00:00
{
2021-07-02 20:23:20 +02:00
PrepareEnvStruct ( info );
2021-06-16 14:16:49 +02:00
( function )( info );
2011-04-26 17:17:06 +00:00
last_res = info . res ;
2010-11-22 01:23:32 +00: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 17:46:24 +00:00
std :: vector < Var > & parameters ,
2014-10-17 21:36:55 +00:00
StreamType & out_stream ,
const StreamType & in_stream )
2011-01-26 12:42:49 +00:00
{
2021-07-02 20:23:20 +02:00
if ( ! IsTestingFunctionExistence () )
2011-01-26 12:42:49 +00: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 );
}
2011-01-26 12:42:49 +00:00
}
}
2014-10-28 17:46:24 +00:00
2015-06-14 18:20:00 +00: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 18:20:00 +00: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 18:20:00 +00: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-06-22 18:01:47 +02:00
{
return true ;
}
}
}
return false ;
}
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-27 22:42:00 +02:00
{
return HasParam ( parameters , L "dump" , L "dump_to_space" );
}
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-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 >
2021-08-17 17:33:51 +02:00
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-08-14 19:40:05 +02:00
bool only_date = HasParam ( parameters , L "only_date" );
bool only_time = HasParam ( parameters , L "only_time" );
2021-07-01 23:21:20 +02:00
2021-08-14 19:40:05 +02:00
if ( only_date )
{
date -> SerializeYearMonthDay ( out_stream , is_roman );
}
else
if ( only_time )
{
if ( is_no_sec )
date -> SerializeHourMin ( out_stream );
else
date -> SerializeHourMinSec ( out_stream );
}
else
{
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 >
2021-08-17 17:33:51 +02:00
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 >
2021-08-17 17:33:51 +02:00
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
{
2022-07-29 03:24:19 +02:00
if ( IsTestingFunctionExistence () )
{
last_res = true ;
}
else
2021-07-02 20:23:20 +02:00
{
DumpSpaceIfNeeded ( parameters , out_stream , space );
2022-07-29 03:24:19 +02:00
last_res = space -> object_size () > 0 ;
2021-07-02 20:23:20 +02:00
}
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 >
2021-09-23 04:02:34 +02:00
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream >:: CallSpaceTableForLastField (
morm :: SpaceWrapper & space_wrapper , std :: vector < Var > & parameters , StreamType & out_stream , pt :: Space * space , size_t model_wrapper_space_table_index )
2021-06-25 16:16:30 +02:00
{
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
2022-07-29 03:24:19 +02:00
if ( IsTestingFunctionExistence () )
{
last_res = true ;
}
else
{
last_res = ! table -> empty ();
}
2021-06-25 16:16:30 +02:00
}
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-09-23 14:03:26 +02:00
if ( HasParam ( parameters , L "index" ) )
{
out_stream << space_wrapper . get_space_iterator_value ( model_wrapper_space_table_index );
}
if ( HasParam ( parameters , L "index-one" ) )
{
out_stream << ( space_wrapper . get_space_iterator_value ( model_wrapper_space_table_index ) + 1 );
}
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-09-23 04:02:34 +02:00
size_t model_wrapper_space_table_index = 0 ;
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
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-09-23 04:02:34 +02:00
// increment field_index only if next_field is 'this' and space is not an object
if ( space && ! space -> is_object () )
{
std :: wstring & next_field = fields [ field_index ];
if ( next_field == L "this" )
{
field_index += 1 ;
}
}
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 )
{
2022-07-29 03:24:19 +02:00
if ( IsTestingFunctionExistence () )
{
last_res = true ;
}
else
2021-07-02 20:23:20 +02:00
{
PrintLastSpaceField ( space , parameters , out_stream );
2022-07-29 03:24:19 +02:00
last_res = space -> to_bool ();
2021-07-02 20:23:20 +02:00
}
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-09-23 04:02:34 +02:00
model_wrapper_space_table_index += 1 ;
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 >
2021-08-17 17:33:51 +02:00
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 );
2023-02-22 00:38:36 +01:00
PrepareEnvStruct ( info );
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 );
2023-02-22 00:38:36 +01:00
PrepareEnvStruct ( info );
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-08-17 17:33:51 +02:00
std :: vector < Var > & parameters , StreamType & out_stream , const StreamType & in_stream )
2021-07-01 23:21:20 +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
2022-07-29 03:24:19 +02:00
// at the moment we do not set last_res
// we don't know whether the last object has properties (fields) or not
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-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-06-16 14:16:49 +02:00
{
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 ;
2021-05-31 18:37:09 +02:00
2021-07-01 23:21:20 +02:00
if ( find_helper . wrapper -> model )
2021-05-31 18:37:09 +02:00
{
2021-07-01 23:21:20 +02:00
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 )
{
morm :: Wrapper new_wrapper = model -> get_wrapper ( nullptr , field . c_str ());
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-08-17 17:33:51 +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-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-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-06-23 06:53:43 +02:00
2021-07-01 23:21:20 +02:00
if ( find_helper . wrapper -> model )
{
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
}
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 18:20:00 +00: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 18:20:00 +00: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 18:20:00 +00: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 17:46:24 +00:00
std :: vector < Var > & parameters ,
2014-10-17 21:36:55 +00: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 21:36:55 +00:00
2021-07-02 20:23:20 +02:00
block_stack . was_return = false ;
block_stack . args = parameters ;
2014-10-17 21:36:55 +00: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 21:36:55 +00:00
2021-07-02 20:23:20 +02:00
MakeText ( item_block );
2014-10-17 21:36:55 +00: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 21:36:55 +00:00
2021-07-02 20:23:20 +02:00
ClearStream ( * output_stream );
output_stream = old_stream ;
block_stack_index -= 1 ;
}
2014-10-17 21:36:55 +00:00
return true ;
}
2010-11-22 01:23:32 +00:00
2011-04-26 17:17:06 +00: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 21:36:55 +00:00
StreamType & out_stream ,
bool clear_out_stream ,
const StreamType & in_stream )
2010-11-22 01:23:32 +00:00
{
2021-06-16 14:16:49 +02:00
FindHelper find_helper ;
2014-10-28 17:46:24 +00:00
std :: vector < Var > parameters ;
2010-11-22 01:23:32 +00:00
2014-10-17 21:36:55 +00:00
if ( clear_out_stream )
ClearStream ( out_stream );
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 ;
2021-05-31 18:37:09 +02:00
2021-06-19 20:18:30 +02:00
if ( ! find_helper . fun_name )
find_helper . fun_name = & item_fun . name ;
if ( ! Find ( item_fun , find_helper ) )
2021-06-16 14:16:49 +02:00
return false ;
2010-11-25 22:39:58 +00:00
2014-10-28 17:46:24 +00:00
parameters . resize ( item_fun . parameters . size ());
2014-10-17 21:36:55 +00:00
for ( size_t i = 0 ; i < item_fun . parameters . size () ; ++ i )
{
Item :: Function & fun_child = * item_fun . parameters [ i ];
2015-03-08 02:31:21 +00:00
if ( fun_child . is_function )
2014-10-17 21:36:55 +00:00
{
2014-10-28 17:46:24 +00: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 21:36:55 +00:00
2021-06-20 16:54:55 +02:00
CopyStreamToString ( local_temp_stream , parameters [ i ]. str );
2014-10-28 17:46:24 +00:00
parameters [ i ]. res = last_res ;
2014-10-17 21:36:55 +00:00
}
2014-10-28 17:46:24 +00:00
else
2014-10-17 21:36:55 +00:00
{
2015-03-08 02:31:21 +00:00
parameters [ i ]. str = fun_child . name ;
parameters [ i ]. res = ConvertToBool ( fun_child . name );
2014-10-17 21:36:55 +00: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 18:20:00 +00: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 21:36:55 +00: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 21:36:55 +00: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 22:39:58 +00:00
2021-05-23 10:02:51 +02:00
return true ;
2010-11-22 01:23:32 +00:00
}
2010-11-25 22:39:58 +00:00
2011-04-26 17:17:06 +00: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-14 23:59:30 +00:00
{
2024-07-07 21:55:49 +02:00
bool status = Call ( item_fun , nullptr , stream_temp1 , true , empty_stream );
ClearStream ( stream_temp1 );
return status ;
2011-01-14 23:59:30 +00:00
}
2010-11-25 22:39:58 +00: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 01:23:32 +00: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 01:55:32 +00: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-25 01:55:32 +00:00
{
wchar_t special = 0 ;
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-22 01:23:32 +00:00
{
2013-11-07 10:16:10 +00:00
if ( output_stream )
2010-11-22 01:23:32 +00:00
{
2013-11-07 10:16:10 +00:00
while ( start != end )
{
const wchar_t * end2 = start ;
2010-11-22 01:23:32 +00:00
2013-11-07 10:16:10 +00: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 01:23:32 +00:00
2013-11-07 10:16:10 +00:00
// printing the first part of the text
if ( start != end2 )
output_stream -> write ( start , end2 - start );
2010-11-22 01:23:32 +00:00
2013-11-07 10:16:10 +00: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 01:23:32 +00: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 01:23:32 +00:00
{
2013-11-07 10:16:10 +00:00
if ( output_stream )
2010-11-22 01:23:32 +00:00
{
2013-11-07 10:16:10 +00:00
if ( skip_new_line )
2010-11-22 01:23:32 +00:00
{
2013-11-07 10:16:10 +00:00
while ( start != end )
{
const wchar_t * end2 = start ;
2010-11-25 01:55:32 +00:00
2013-11-07 10:16:10 +00:00
// looking for a first new line character
while ( end2 != end && * end2 != 10 )
end2 += 1 ;
2010-11-25 01:55:32 +00:00
2013-11-07 10:16:10 +00:00
// printing the first part of the text (until the new line)
if ( start != end2 )
output_stream -> write ( start , end2 - start );
2010-11-25 01:55:32 +00:00
2013-11-07 10:16:10 +00: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 01:23:32 +00: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 19:56:48 +00: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 01:23:32 +00:00
{
2014-10-11 19:56:48 +00:00
while ( start != end && IsWhite ( * start ) )
2010-11-22 01:23:32 +00:00
++ start ;
2014-10-11 19:56:48 +00:00
while ( start != end && IsWhite ( * ( end - 1 )) )
2010-11-22 01:23:32 +00: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 01:23:32 +00:00
{
2014-10-11 19:56:48 +00:00
while ( IsWhite ( * str ) )
2010-11-22 01:23:32 +00: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 01:23:32 +00:00
{
2012-02-24 12:04:36 +00:00
size_t res = 0 ;
2010-11-22 01:23:32 +00:00
SkipWhite ( str );
2012-02-24 12:04:36 +00:00
// !! IMPROVE ME
2010-11-22 01:23:32 +00:00
// overflow is not checked
while ( * str >= '0' && * str <= '9' )
{
res *= 10 ;
res += * str - '0' ;
str += 1 ;
}
SkipWhite ( str );
2013-11-07 10:16:10 +00:00
if ( str_end )
* str_end = str ;
2010-11-22 01:23:32 +00:00
return res ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
2024-07-07 21:55:49 +02:00
StreamType * Generator < StreamType , is_pikotools_stream , is_autoescape_stream >:: FindAddOutputStream ( const std :: wstring & name )
2011-01-26 12:42:49 +00:00
{
2024-07-07 21:55:49 +02:00
StreamType * stream = nullptr ;
2021-05-28 16:10:16 +02:00
if ( output_frames_streams )
2013-11-07 10:16:10 +00:00
{
2024-07-07 21:55:49 +02:00
auto imap = output_frames_streams -> streams_map . find ( name );
2015-11-12 09:53:20 +00:00
2024-07-07 21:55:49 +02:00
if ( imap == output_frames_streams -> streams_map . end () )
2013-11-07 10:16:10 +00:00
{
2024-07-07 21:55:49 +02:00
if ( output_frames_streams -> streams_map . size () < output_frames_streams -> streams_tab . size () )
2015-11-12 09:53:20 +00:00
{
2024-07-07 21:55:49 +02:00
/* a new stream from the pool (output_stream_tab) is taken */
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 );
2015-11-12 09:53:20 +00:00
}
2021-06-20 16:54:55 +02:00
else
{
2024-07-07 21:55:49 +02:00
CreateMsg ( L "limit of output streams in OutStreams<> has been reached" );
}
}
else
{
stream = imap -> second ;
}
}
return stream ;
}
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 )
{
if ( output_frames_streams )
{
for ( size_t s = 0 ; s < fun . parameters . size () ; ++ s )
{
std :: wstring & name = fun . parameters [ s ] -> name ;
if ( HasAskForSuchFrame ( name ) )
{
StreamType * stream = FindAddOutputStream ( name );
if ( stream )
{
CopyStream ( ezc_out_tmp_stream , * stream );
}
2021-06-20 16:54:55 +02:00
}
2013-11-07 10:16:10 +00:00
}
}
2011-01-26 12:42:49 +00: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 )
2010-11-22 01:23:32 +00:00
{
2021-06-19 20:18:30 +02:00
if ( plog )
{
2021-06-20 16:54:55 +02:00
( * plog ) << pt :: Log :: log2 << "Ezc: " << type ;
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 ;
}
2010-11-22 01:23:32 +00: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 )
{
if ( plog )
{
( * plog ) << pt :: Log :: log2 << L "Ezc: " << type << model_name ;
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
}
if ( arg )
{
( * plog ) << arg ;
}
if ( arg2 )
{
( * plog ) << arg2 ;
}
if ( arg3 )
{
( * plog ) << arg3 ;
}
( * plog ) << pt :: Log :: logend ;
}
}
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 01:23:32 +00:00
{
2010-11-25 22:39:58 +00:00
CreateMsg ( type . c_str (), arg . c_str ());
2010-11-22 01:23:32 +00: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 01:23:32 +00:00
{
2010-11-25 22:39:58 +00:00
CreateMsg ( type . c_str ());
2010-11-22 01:23:32 +00: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-29 23:50:10 +00:00
{
if ( output_stream )
{
if ( item . type == Item :: item_function )
2018-10-30 20:59:17 +00:00
* output_stream << " expression: " << item . text ;
2018-10-29 23:50:10 +00:00
if ( item . type == Item :: item_if )
2018-10-30 20:59:17 +00:00
* output_stream << " if: " << item . text ;
2018-10-29 23:50:10 +00:00
if ( item . type == Item :: item_for )
2018-10-30 20:59:17 +00:00
* output_stream << " for: " << item . text ;
2018-10-29 23:50:10 +00:00
}
last_res = false ;
if ( expression_parser )
{
if ( expression_parser -> Parse ( item . text ) )
{
last_res = expression_parser -> LastResultToBool ();
2018-10-30 20:59:17 +00:00
if ( output_stream )
{
* output_stream << " -> " << expression_parser -> LastResult ();
}
2018-10-29 23:50:10 +00:00
}
else
{
if ( output_stream )
{
2018-10-30 20:59:17 +00:00
* output_stream << " -> syntax error when evaluating expression: error code: " << ( int ) expression_parser -> LastError ();
2018-10-29 23:50:10 +00:00
}
}
}
2018-10-30 20:59:17 +00:00
if ( output_stream )
{
* output_stream << " \n " ;
}
2018-10-29 23:50:10 +00:00
}
2024-07-07 21:55:49 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream >:: HasAskForSuchFrame ( Item :: Function & fun )
{
if ( only_frames )
{
for ( size_t s = 0 ; s < fun . parameters . size () ; ++ s )
{
std :: wstring & name = fun . parameters [ s ] -> name ;
for ( size_t f = 0 ; f < only_frames -> size () ; ++ f )
{
const std :: wstring & frame = ( * only_frames )[ f ];
if ( name == frame )
return true ;
}
}
return false ;
}
else
{
return true ;
}
}
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
bool Generator < StreamType , is_pikotools_stream , is_autoescape_stream >:: HasAskForSuchFrame ( const std :: wstring & name )
{
if ( only_frames )
{
for ( size_t f = 0 ; f < only_frames -> size () ; ++ f )
{
const std :: wstring & frame = ( * only_frames )[ f ];
if ( name == frame )
return true ;
}
return false ;
}
else
{
return true ;
}
}
2010-11-22 01:23:32 +00: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 01:23:32 +00:00
{
2024-07-07 21:55:49 +02:00
if ( is_output_stream_allowed )
{
const wchar_t * start = item . text . c_str ();
const wchar_t * end = item . text . c_str () + item . text . size ();
2010-11-22 01:23:32 +00:00
2024-07-07 21:55:49 +02:00
if ( trim_white )
TrimWhite ( start , end );
2010-11-22 01:23:32 +00:00
2024-07-07 21:55:49 +02:00
if ( special_chars )
PrintSpecialText ( start , end );
else
PrintNormalText ( start , end );
}
2010-11-22 01:23:32 +00: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 >:: MakeTextContainer ( Item & item )
2010-11-22 01:23:32 +00:00
{
std :: vector < Item *>:: iterator i = item . item_tab . begin ();
for ( ; i != item . item_tab . end () && ! break_generating ; ++ i )
2011-07-15 02:09:40 +00:00
MakeText ( ** i );
2010-11-22 01:23:32 +00: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 01:23:32 +00:00
{
2012-02-24 12:04:36 +00:00
is_generating_normal = true ;
2013-11-07 10:16:10 +00:00
2018-10-29 23:50:10 +00:00
if ( program_mode )
2013-11-07 10:16:10 +00:00
{
2018-10-29 23:50:10 +00:00
EvaluateProgramNode ( item );
2013-11-07 10:16:10 +00:00
}
else
{
2024-07-07 21:55:49 +02:00
if ( output_stream && is_output_stream_allowed )
2018-10-29 23:50:10 +00:00
{
2021-05-23 10:02:51 +02:00
Call ( item . function , nullptr , * output_stream , false , empty_stream );
2018-10-29 23:50:10 +00:00
}
else
{
2021-05-23 10:02:51 +02:00
Call ( item . function , nullptr , stream_temp1 , false , empty_stream );
2018-10-29 23:50:10 +00:00
ClearStream ( stream_temp1 );
}
2013-11-07 10:16:10 +00:00
}
2010-11-22 01:23:32 +00: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 01:23:32 +00: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 01:23:32 +00:00
{
2012-02-24 12:04:36 +00:00
is_generating_if = true ;
2018-10-29 23:50:10 +00:00
if ( program_mode )
{
EvaluateProgramNode ( item );
}
else
{
if ( ! Call ( item . function ) )
return ;
}
2010-11-22 01:23:32 +00:00
2011-04-26 17:17:06 +00:00
MakeTextIf_go ( item , last_res );
2010-11-22 01:23:32 +00: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 01:23:32 +00: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 01:23:32 +00:00
{
2012-03-03 20:58:55 +00:00
stack_tab [ stack_index - 1 ]. is_for = true ;
2012-02-27 17:39:46 +00:00
for ( ; ! break_generating ; stack_tab [ stack_index - 1 ]. iter += 1 )
2010-11-22 01:23:32 +00:00
{
2012-02-27 17:39:46 +00:00
if ( stack_tab [ stack_index - 1 ]. iter >= max_for_items )
2010-11-22 01:23:32 +00:00
{
2015-03-08 02:31:21 +00:00
CreateMsg ( item . function . name . c_str (),
2010-11-22 01:23:32 +00:00
L "function exceeded a limit for a [for] statement" );
break ;
}
2012-01-17 22:57:06 +00: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-29 23:50:10 +00:00
if ( program_mode )
{
EvaluateProgramNode ( item );
}
else
{
2022-08-01 15:20:02 +02:00
if ( ! Call ( item . function , nullptr , stream_temp1 , true , empty_stream ) )
return ;
2018-10-29 23:50:10 +00:00
}
2010-11-22 01:23:32 +00:00
2011-04-26 17:17:06 +00:00
if ( ! last_res )
2010-11-22 01:23:32 +00:00
break ;
if ( ! item . item_tab . empty () )
2018-10-29 23:50:10 +00:00
MakeText ( * item . item_tab [ 0 ] ); // should be only one item
2010-11-22 01:23:32 +00: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 )
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 () )
{
return ;
}
if ( item . function . parameters . size () > 1 )
{
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 ) )
{
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 ;
}
else
{
CreateMsg ( L "[def] unknown function/block/variable" , item . function . name );
}
}
else
{
var . str = fun . name ;
var . res = ConvertToBool ( fun . name );
}
}
2010-11-22 01:23:32 +00: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 )
2010-11-22 01:23:32 +00:00
{
2021-05-23 10:02:51 +02:00
if ( ! can_use_vars || ! pvars )
2010-11-25 22:39:58 +00:00
{
2014-10-17 21:36:55 +00:00
CreateMsg ( L "[def] statement not available" );
2010-11-25 22:39:58 +00:00
return ;
}
2014-10-17 21:36:55 +00:00
2021-05-23 10:02:51 +02:00
Var & var = ( * pvars )[ item . function . name ];
MakeTextDefine ( item , var );
}
2015-03-08 02:31:21 +00: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 >
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 );
2010-11-22 01:23:32 +00: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 , 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 );
}
}
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 );
}
}
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 12:42:49 +00:00
{
if ( filter_index >= filter_tab . size () )
{
CreateMsg ( L "Generator exceeded allowed number of filters" );
return ;
}
2013-11-07 10:16:10 +00:00
2011-01-26 12:42:49 +00: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 12:04:36 +00:00
is_generating_filter = true ;
2011-01-26 12:42:49 +00:00
2024-07-07 21:55:49 +02:00
if ( old_stream && is_output_stream_allowed )
2013-11-07 10:16:10 +00:00
{
2021-05-23 10:02:51 +02:00
Call ( item . function , nullptr , * old_stream , false , * output_stream );
2013-11-07 10:16:10 +00:00
}
else
{
2021-05-23 10:02:51 +02:00
Call ( item . function , nullptr , stream_temp1 , true , * output_stream );
2013-11-07 10:16:10 +00:00
ClearStream ( stream_temp1 );
}
ClearStream ( * output_stream );
2011-01-26 12:42:49 +00:00
output_stream = old_stream ;
filter_index -= 1 ;
}
2021-07-12 23:00:11 +02:00
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
2024-07-07 21:55:49 +02:00
StreamType * Generator < StreamType , is_pikotools_stream , is_autoescape_stream >:: GetNewStreamForFrame ()
2013-11-07 10:16:10 +00:00
{
2021-05-28 16:10:16 +02:00
if ( ezc_frames_stack_index >= ezc_frame_stack_tab . size () )
2013-11-07 10:16:10 +00:00
{
2021-05-28 16:10:16 +02:00
CreateMsg ( L "Generator exceeded allowed number of [ezc frame] statements" );
2024-07-07 21:55:49 +02:00
return nullptr ;
2013-11-07 10:16:10 +00:00
}
2024-07-07 21:55:49 +02:00
StreamType * stream = ezc_frame_stack_tab [ ezc_frames_stack_index ];
ClearStream ( * stream );
ezc_frames_stack_index += 1 ;
return stream ;
}
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream >:: DecrementFramesStackIndex ()
{
if ( ezc_frames_stack_index > 0 )
{
ezc_frames_stack_index -= 1 ;
}
}
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream >:: MakeEzcFrame2 ( Item & item )
{
StreamType * old_stream = output_stream ;
bool old_is_output_stream_allowed = is_output_stream_allowed ;
2024-07-08 00:34:52 +02:00
bool put_directly = false ;
2024-07-07 21:55:49 +02:00
bool is_current_frame_allowed = HasAskForSuchFrame ( item . function );
if ( ! is_output_stream_allowed && is_current_frame_allowed )
{
is_output_stream_allowed = true ;
}
if ( ! old_is_output_stream_allowed && is_current_frame_allowed && item . function . parameters . size () == 1 )
{
/*
* some optimization, put directly to the frame stream
*/
2024-07-08 00:34:52 +02:00
put_directly = true ;
2024-07-07 21:55:49 +02:00
output_stream = FindAddOutputStream ( item . function . parameters [ 0 ] -> name );
}
else
2024-07-08 00:34:52 +02:00
if ( old_is_output_stream_allowed && ! is_current_frame_allowed )
{
/*
* some optimization, put directly to the old stream
*/
put_directly = true ;
// do not modify output_stream here
}
else
2024-07-07 21:55:49 +02:00
{
output_stream = GetNewStreamForFrame ();
}
if ( output_stream )
{
if ( ! item . item_tab . empty () )
MakeText ( * item . item_tab [ 0 ] ); // should be only one item - item_container
2024-07-08 00:34:52 +02:00
if ( ! put_directly )
2024-07-07 21:55:49 +02:00
{
if ( old_is_output_stream_allowed )
{
CopyStream ( * output_stream , * old_stream );
}
if ( is_current_frame_allowed )
{
CopyTmpStreamToOutputStreams ( item . function , * output_stream );
}
ClearStream ( * output_stream );
DecrementFramesStackIndex ();
}
}
is_output_stream_allowed = old_is_output_stream_allowed ;
output_stream = old_stream ;
}
template < class StreamType , bool is_pikotools_stream , bool is_autoescape_stream >
void Generator < StreamType , is_pikotools_stream , is_autoescape_stream >:: MakeEzcFrame ( Item & item )
{
2015-11-12 09:53:20 +00: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 09:53:20 +00: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 )
2013-11-07 10:16:10 +00:00
{
2024-07-07 21:55:49 +02:00
if ( ! item . item_tab . empty () )
MakeText ( * item . item_tab [ 0 ] ); // should be only one item - item_container
2013-11-07 10:16:10 +00:00
}
2024-07-07 21:55:49 +02:00
else
2013-11-07 10:16:10 +00:00
{
2024-07-07 21:55:49 +02:00
MakeEzcFrame2 ( item );
2013-11-07 10:16:10 +00: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 10:16:10 +00: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 10:16:10 +00:00
2015-03-08 02:31:21 +00:00
// in the future we can use more builtin functions
2013-11-07 10:16:10 +00: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 17:46:24 +00: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 02:31:21 +00:00
if ( item . has_function )
2014-10-28 17:46:24 +00:00
{
2015-03-08 02:31:21 +00:00
// output stream in [return] statement is ignored (we use only the stream produced by the whole block)
2014-10-28 17:46:24 +00: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 17:46:24 +00:00
ClearStream ( stream_temp1 );
}
}
2013-11-07 10:16:10 +00:00
2014-10-17 21:36:55 +00: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 01:23:32 +00:00
{
if ( break_generating )
2012-02-27 17:39:46 +00:00
return true ;
2014-10-28 17:46:24 +00:00
if ( current_item >= max_items )
2010-11-22 01:23:32 +00:00
{
break_generating = true ;
2010-11-25 22:39:58 +00:00
CreateMsg ( L "Generator exceeded allowed number of elements" );
2012-02-27 17:39:46 +00:00
return true ;
2010-11-22 01:23:32 +00:00
}
2014-10-28 17:46:24 +00:00
if ( stack_index >= stack_tab . size () )
2012-02-27 17:39:46 +00:00
{
break_generating = true ;
CreateMsg ( L "Generator exceeded the stack size" );
return true ;
}
2014-10-28 17:46:24 +00: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 17:39:46 +00: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 17:39:46 +00: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 22:57:06 +00:00
2012-02-27 17:39:46 +00:00
stack_tab [ stack_index - 1 ]. Clear ();
2016-04-04 15:53:11 +00:00
stack_tab [ stack_index - 1 ]. item = & item ;
2012-02-27 17:39:46 +00: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 01:23:32 +00:00
else if ( item . type == Item :: item_err )
2010-11-25 22:39:58 +00:00
CreateMsg ( L "a wrong directive" );
2012-02-27 17:39:46 +00:00
RemoveStackFunData ( stack_tab [ stack_index - 1 ]);
stack_index -= 1 ;
2010-11-22 01:23:32 +00:00
}
} // namespace Ezc
#endif
2014-11-02 17:26:56 +00:00