diff --git a/src/funinfo.h b/src/funinfo.h index c3ef8ff..b14cdb1 100755 --- a/src/funinfo.h +++ b/src/funinfo.h @@ -47,6 +47,19 @@ namespace Ezc { +struct FunData +{ + + + FunData() + { + } + + virtual ~FunData() + { + } +}; + template struct FunInfo @@ -75,21 +88,47 @@ struct FunInfo // indicates that this function is from [for ...] statement bool is_for; - // indicates that this function is from [for ...] statement - // and this is a first iteration (iter=0 too) - // this is only for convenience -- you don't have to check is_for and iter==0 - // !! may a better name? - bool is_for_first_iter; + // indicates that this function is from [if ...] statement + // is true for all kind of if's: if-one, if-any, if-no.... + bool is_if; + + // indicates that this function is from [is ...] or [is-no ...] statements + bool is_is; + + // indicates that this funcion is a normal statement e.g.: [funcion_name] + bool is_normal; + + // indicates that this function is from a filter statement [filter ...] + bool is_filter; + + // a pointer to FunData struct + // !! IMPROVE ME + // !! give some info here + // can be null + FunData * fun_data; + + + + FunData * last_fun_data; + // this is set by Generator - // it indicates the number of a current iteration in the last [for] statement (the first is 0) + // it indicates the number of a current iteration for the [for] statement (the first iteration is 0) // if there was not any [for] before the value is zero - int iter; + // for other statements than [for] this is always zero + size_t iter; + + // this is set by Generator + // it indicates the number of a previous [for] iteration + // if there was not any [for] before the value is zero + // for a [for] it returns not the current iterator but a value from a previous [for] + size_t last_iter; // return value from a user function (default false if not set directly by the user function) // for a variable it is set to true if the variable is not empty bool res; + // arguments: output_stream, table_of_parameters, the_first_parameter FunInfo(StreamType & o, std::vector & pars, @@ -99,13 +138,20 @@ struct FunInfo Clear(); } + void Clear() { - res = false; // result is false by default - is_for = false; - is_for_first_iter = false; - iter = 0; - case_sensitive = true; + res = false; // result is false by default + is_for = false; + is_if = false; + is_is = false; + is_normal = false; + is_filter = false; + iter = 0; + last_iter = 0; + case_sensitive = true; + fun_data = 0; + last_fun_data = 0; } }; diff --git a/src/generator.h b/src/generator.h index 4cd22d5..5d858dc 100755 --- a/src/generator.h +++ b/src/generator.h @@ -63,7 +63,7 @@ public: ~Generator(); - void SetMax(int max_items_, int max_for_items_); + void SetMax(size_t max_items_, size_t max_for_items_); // recognizing some special characters in text patterns (item_text in Patterns) // \r will be a carriage return (13) @@ -106,9 +106,9 @@ private: std::wstring temp_msg; bool break_generating; - int current_item; - int max_items; - int max_for_items; + size_t current_item; + size_t max_items; + size_t max_for_items; bool special_chars; bool trim_white; bool skip_new_line; @@ -132,8 +132,12 @@ private: // true if this Generator is working now bool is_generator_working; - // true if the Generator is working with [for ...] statement + // true if the Generator is working with [for ...], [if ...] etc. bool is_generating_for; + bool is_generating_if; + bool is_generating_is; + bool is_generating_normal; + bool is_generating_filter; // an empty string for FunInfo objects // when there is no any parameters @@ -143,7 +147,14 @@ private: // currently only one item (iterator) struct StackItem { - int iter; + size_t iter; + FunData * fun_data; + + StackItem() + { + iter = 0; + fun_data = 0; + } }; // a stack for [for] statements @@ -152,6 +163,7 @@ private: void ResizeFilterTab(); void ClearFilterTab(); + void ClearForStack(); void ClearStream(StreamType & str); template @@ -179,7 +191,7 @@ private: void PrintNormalText(const wchar_t * start, const wchar_t * end); void TrimWhite(const wchar_t *& start, const wchar_t *& end); void SkipWhite(const wchar_t *& str); - int StrToInt(const wchar_t * str, const wchar_t ** str_end); + size_t StrToSize(const wchar_t * str, const wchar_t ** str_end); void CreateMsg(StreamType & out, const wchar_t * type, const wchar_t * arg = 0); void CreateMsg(const wchar_t * type, const wchar_t * arg = 0); @@ -257,7 +269,10 @@ Generator & Generator::operator=(const Generator Generator::~Generator() { ClearFilterTab(); + ClearForStack(); } @@ -305,6 +321,16 @@ void Generator::ClearFilterTab() } +template +void Generator::ClearForStack() +{ + for(size_t i=0 ; i void Generator::ClearStream(StreamType & str) { @@ -362,7 +388,7 @@ bool Generator::AreStreamsEqual(StreamType & str1, StreamType & str2 template -void Generator::SetMax(int max_items_, int max_for_items_) +void Generator::SetMax(size_t max_items_, size_t max_for_items_) { max_items = max_items_; max_for_items = max_for_items_; @@ -415,7 +441,7 @@ void Generator::Generate(StreamType * o, Pattern * p, Functions::Call(typename Functions::Function * func { info.Clear(); - if( stack_tab.empty() ) - info.iter = 0; - else - info.iter = stack_tab.back().iter; + info.is_for = is_generating_for; + info.is_if = is_generating_if; + info.is_is = is_generating_is; + info.is_normal = is_generating_normal; + info.is_filter = is_generating_filter; - info.is_for = is_generating_for; - info.is_for_first_iter = (info.is_for && info.iter == 0); + if( info.is_for ) + { + if( !stack_tab.empty() ) + info.iter = stack_tab.back().iter; + + if( stack_tab.size() >= 2 ) + info.last_iter = stack_tab[stack_tab.size()-2].iter; + } + else + { + if( !stack_tab.empty() ) + info.last_iter = stack_tab.back().iter; + } + + if( !stack_tab.empty() ) + info.fun_data = stack_tab.back().fun_data; + + if( stack_tab.size() >= 2 ) + info.last_fun_data = stack_tab[stack_tab.size()-2].fun_data; if( function->type == Functions::function ) { @@ -508,6 +552,22 @@ void Generator::Call(typename Functions::Function * func info.res = !function->variable.empty(); } + if( info.fun_data ) + { + if( !stack_tab.empty() ) + { + if( stack_tab.back().fun_data != info.fun_data ) + { + delete stack_tab.back().fun_data; + stack_tab.back().fun_data = info.fun_data; + } + } + else + { + delete info.fun_data; + } + } + last_res = info.res; last_case_sensitive = info.case_sensitive; } @@ -699,12 +759,13 @@ void Generator::SkipWhite(const wchar_t *& str) template -int Generator::StrToInt(const wchar_t * str, const wchar_t ** str_end) +size_t Generator::StrToSize(const wchar_t * str, const wchar_t ** str_end) { -int res = 0; +size_t res = 0; SkipWhite(str); + // !! IMPROVE ME // overflow is not checked while( *str>='0' && *str<='9' ) @@ -797,6 +858,7 @@ void Generator::MakeTextNormal(Item & item) if( item.functions.size() != 1 ) return; + is_generating_normal = true; Call(item.functions[0], *output_stream, false); } @@ -826,6 +888,8 @@ void Generator::MakeTextIf(Item & item) if( item.functions.size() != 1 ) return; + is_generating_if = true; + if( !Call(item.functions[0]) ) return; @@ -839,6 +903,8 @@ void Generator::MakeTextIfno(Item & item) if( item.functions.size() != 1 ) return; + is_generating_if = true; + if( !Call(item.functions[0]) ) return; @@ -852,6 +918,8 @@ void Generator::MakeTextIfany(Item & item) std::vector::iterator d = item.functions.begin(); unsigned how_many_true = 0; + is_generating_if = true; + for( ; d != item.functions.end() ; ++d ) { if( !Call(*d) ) @@ -871,6 +939,8 @@ void Generator::MakeTextIfone(Item & item) std::vector::iterator d = item.functions.begin(); unsigned how_many_true = 0; + is_generating_if = true; + for( ; d != item.functions.end() ; ++d ) { if( Call(*d) ) @@ -893,6 +963,8 @@ void Generator::MakeTextIfanyno(Item & item) std::vector::iterator d = item.functions.begin(); unsigned how_many_true = 0; + is_generating_if = true; + for( ; d != item.functions.end() ; ++d ) { if( !Call(*d) ) @@ -912,6 +984,8 @@ void Generator::MakeTextIfoneno(Item & item) std::vector::iterator d = item.functions.begin(); unsigned how_many_false = 0; + is_generating_if = true; + for( ; d != item.functions.end() ; ++d ) { if( Call(*d) ) @@ -935,6 +1009,8 @@ void Generator::MakeTextIs(Item & item, bool equal) if( item.functions.size() != 2 ) return; + is_generating_is = true; + // if one of these two functions has set case_sensitive to false // then we compare in case insensitive mode bool case_sensitive = true; @@ -990,7 +1066,7 @@ bool Generator::MakeTextIfindexnumber(Item & item, bool & result) const wchar_t * number_text = item.functions[0].name.c_str(); const wchar_t * last_char; - int number = StrToInt(number_text, &last_char); + size_t number = StrToSize(number_text, &last_char); if( *last_char != '\0' ) { @@ -1078,12 +1154,11 @@ void Generator::MakeTextFor(Item & item) if( !Find(item.functions[0], &function) ) return; - StackItem s; - s.iter = 0; - stack_tab.push_back(s); + stack_tab.push_back(StackItem()); MakeTextForLoop(item, function); + delete stack_tab.back().fun_data; stack_tab.erase(--stack_tab.end()); } @@ -1154,6 +1229,7 @@ void Generator::MakeTextFilter(Item & item) if( !item.item_tab.empty() ) MakeText( *item.item_tab[0] ); // should be only one item - item_container + is_generating_filter = true; Call(function, item.functions[0].params, *old_stream, false, *output_stream); output_stream = old_stream; @@ -1175,7 +1251,11 @@ void Generator::MakeText(Item & item) return; } - is_generating_for = false; + is_generating_for = false; + is_generating_if = false; + is_generating_is = false; + is_generating_normal = false; + is_generating_filter = false; if ( item.type == Item::item_text ) MakeItemText(item); else if( item.type == Item::item_container )MakeTextContainer(item);