diff --git a/src/funinfo.h b/src/funinfo.h index 65f3c57..3ffd4a0 100755 --- a/src/funinfo.h +++ b/src/funinfo.h @@ -54,6 +54,11 @@ struct FunInfo // output stream StreamType & out; + // the out stream is treated in case sensitive + // used only in [is...] statements + // default: true + bool case_sensitive; + // table of parameters // the table can be empty std::vector & params; @@ -89,6 +94,7 @@ struct FunInfo { res = false; // false by default iter = 0; + case_sensitive = true; } }; diff --git a/src/generator.h b/src/generator.h index 6ba213b..1e29887 100755 --- a/src/generator.h +++ b/src/generator.h @@ -120,37 +120,54 @@ private: std::vector filter_tab; const StreamType empty_stream; + // temporary streams used in [if..] [is...] or [for...] + StreamType stream_temp1, stream_temp2; - bool is_used; + // whether last function has put its content in case_sensitive (set FunInfo::case_sensitive) + bool last_case_sensitive; + // last result from a user function (FunInfo::res) + bool last_res; - // an empty string for info objects + // true if this Generator is working now + bool is_generator_working; + + // an empty string for FunInfo objects // when there is no any parameters const std::wstring empty; - - // a stack item for 'for' statements - // currently only one item (iteration) + // a stack item for [for] statements + // currently only one item (iterator) struct StackItem { int iter; }; - // a stack for 'for' statements + // a stack for [for] statements std::vector stack_tab; + void ResizeFilterTab(); void ClearFilterTab(); void ClearStream(StreamType & str); + template + CharType ToLower(CharType c); + + template + bool StrCmpNc(CharType * str1, CharType * str2); + + bool AreStreamsEqual(StreamType & str1, StreamType & str2, bool case_sensitive); + + bool Find(const Item::Function & item_fun, typename Functions::Function ** function); void Call(typename Functions::Function * function, FunInfo & info); void Call(typename Functions::Function * function, std::vector & params, - StreamType & out_stream, const StreamType & in_stream, bool * info_res = 0); + StreamType & out_stream, bool clear_out_stream, const StreamType & in_stream); - bool Call(Item::Function & function, bool * info_res = 0, typename Functions::Function ** pfun = 0); - void Call(typename Functions::Function * function, std::vector & params, bool * info_res = 0); + bool Call(Item::Function & item_fun, StreamType & out_stream, bool clear_out_stream); + bool Call(Item::Function & function); wchar_t CreateSpecialChar(wchar_t c); @@ -181,6 +198,7 @@ private: void MakeItemText(Item & item); void MakeTextContainer(Item & item); void MakeTextNormal(Item & item); + void MakeTextIs(Item & item, bool equal); void MakeTextIs(Item & item); void MakeTextIsno(Item & item); void MakeTextDefine(Item & item); @@ -209,7 +227,7 @@ Generator::Generator() special_chars = false; trim_white = false; skip_new_line = false; - is_used = false; + is_generator_working = false; } @@ -238,8 +256,8 @@ Generator & Generator::operator=(const Generator::ClearStream(StreamType & str) } +template +template +CharType Generator::ToLower(CharType c) +{ + if( c>='A' && c<='Z' ) + return c - 'A' + 'a'; + +return c; +} + + +template +template +bool Generator::StrCmpNc(CharType * str1, CharType * str2) +{ + for( ; ToLower(*str1) == ToLower(*str2) ; ++str1, ++str2) + if( *str1 == 0 ) + return true; + +return false; +} + + +template +bool Generator::AreStreamsEqual(StreamType & str1, StreamType & str2, bool case_sensitive) +{ + if( case_sensitive ) + { + #ifdef EZC_HAS_SPECIAL_STREAM + return str1.Str() == str2.Str(); + #else + return str1.str() == str2.str(); + #endif + } + else + { + #ifdef EZC_HAS_SPECIAL_STREAM + return StrCmpNc(str1.CStr(), str2.CStr()); + #else + return StrCmpNc(str1.str().c_str(), str2.str().c_str()); + #endif + } +} + + template void Generator::SetMax(int max_items_, int max_for_items_) { @@ -335,7 +398,7 @@ void Generator::SetMaxFilters(size_t new_len) template void Generator::Generate(StreamType * o, Pattern * p, Functions * f) { - if( is_used ) + if( is_generator_working ) { if( o ) CreateMsg(*o, L"generator busy"); @@ -357,13 +420,13 @@ void Generator::Generate(StreamType * o, Pattern * p, Functionsitem_root ); - is_used = false; + is_generator_working = false; } catch(...) { - is_used = false; + is_generator_working = false; throw; } } @@ -430,9 +493,18 @@ void Generator::Call(typename Functions::Function * func info.iter = stack_tab.back().iter; if( function->type == Functions::function ) + { (function->user_function)(info); + } else + { + info.out << function->variable; info.res = !function->variable.empty(); + info.case_sensitive = true; + } + + last_res = info.res; + last_case_sensitive = info.case_sensitive; } @@ -440,54 +512,49 @@ void Generator::Call(typename Functions::Function * func template void Generator::Call(typename Functions::Function * function, std::vector & params, - StreamType & out_stream, const StreamType & in_stream, - bool * info_res) + StreamType & out_stream, + bool clear_out_stream, + const StreamType & in_stream) { + if( clear_out_stream ) + ClearStream(out_stream); + if( params.empty() ) { FunInfo info(out_stream, params, empty, in_stream); Call(function, info); - - if( info_res ) - *info_res = info.res; } else { FunInfo info(out_stream, params, params[0], in_stream); Call(function, info); - - if( info_res ) - *info_res = info.res; } } + // return: true if a function or variable was found and called template -bool Generator::Call(Item::Function & item_fun, bool * info_res, typename Functions::Function ** pfun) +bool Generator::Call(Item::Function & item_fun, StreamType & out_stream, bool clear_out_stream) { typename Functions::Function * fun; if( !Find(item_fun, &fun) ) return false; - Call(fun, item_fun.params, *output_stream, empty_stream, info_res); - - if( pfun ) - *pfun = fun; + Call(fun, item_fun.params, out_stream, clear_out_stream, empty_stream); return true; } - -// it calls the function pointed by pfun +// return: true if a function or variable was found and called template -void Generator::Call(typename Functions::Function * function, std::vector & params, bool * info_res) +bool Generator::Call(Item::Function & item_fun) { - Call(function, params, *output_stream, empty_stream, info_res); + return Call(item_fun, stream_temp1, true); } @@ -725,11 +792,7 @@ void Generator::MakeTextNormal(Item & item) if( item.functions.size() != 1 ) return; - typename Functions::Function * pfun; - bool called = Call(item.functions[0], 0, &pfun); - - if( called && pfun->type == Functions::variable ) - (*output_stream) << pfun->variable; + Call(item.functions[0], *output_stream, false); } @@ -755,30 +818,26 @@ void Generator::MakeTextIf_go(Item & item, bool result) template void Generator::MakeTextIf(Item & item) { -bool info_res; - if( item.functions.size() != 1 ) return; - if( !Call(item.functions[0], &info_res) ) + if( !Call(item.functions[0]) ) return; - MakeTextIf_go(item, info_res); + MakeTextIf_go(item, last_res); } template void Generator::MakeTextIfno(Item & item) { -bool info_res; - if( item.functions.size() != 1 ) return; - if( !Call(item.functions[0], &info_res) ) + if( !Call(item.functions[0]) ) return; - MakeTextIf_go(item, !info_res); + MakeTextIf_go(item, !last_res); } @@ -787,14 +846,13 @@ void Generator::MakeTextIfany(Item & item) { std::vector::iterator d = item.functions.begin(); unsigned how_many_true = 0; - bool info_res; for( ; d != item.functions.end() ; ++d ) { - if( !Call(*d, &info_res) ) + if( !Call(*d) ) return; - if( info_res ) + if( last_res ) ++how_many_true; } @@ -807,15 +865,16 @@ void Generator::MakeTextIfone(Item & item) { std::vector::iterator d = item.functions.begin(); unsigned how_many_true = 0; - bool info_res; for( ; d != item.functions.end() ; ++d ) { - if( Call(*d, &info_res) && info_res ) + if( Call(*d) ) { - // there is no sense to go through all functions - ++how_many_true; - break; + if( last_res ) + { + ++how_many_true; + break; // there is no sense to go through all functions + } } } @@ -828,14 +887,13 @@ void Generator::MakeTextIfanyno(Item & item) { std::vector::iterator d = item.functions.begin(); unsigned how_many_true = 0; - bool info_res; for( ; d != item.functions.end() ; ++d ) { - if( !Call(*d, &info_res) ) + if( !Call(*d) ) return; - if( info_res ) + if( last_res ) ++how_many_true; } @@ -848,12 +906,17 @@ void Generator::MakeTextIfoneno(Item & item) { std::vector::iterator d = item.functions.begin(); unsigned how_many_false = 0; - bool info_res; for( ; d != item.functions.end() ; ++d ) { - if( Call(*d, &info_res) && !info_res ) - ++how_many_false; + if( Call(*d) ) + { + if( !last_res ) + { + ++how_many_false; + break; + } + } } MakeTextIf_go(item, how_many_false > 0); @@ -862,38 +925,49 @@ void Generator::MakeTextIfoneno(Item & item) template -void Generator::MakeTextIs(Item & item) +void Generator::MakeTextIs(Item & item, bool equal) { -bool info_res1, info_res2; - if( item.functions.size() != 2 ) return; - if( !Call(item.functions[0], &info_res1) ) + // if one of these two functions has set case_sensitive to false + // then we compare in case insensitive mode + bool case_sensitive = true; + + if( !Call(item.functions[0], stream_temp1, true) ) return; - if( !Call(item.functions[1], &info_res2) ) + if( !last_case_sensitive ) + case_sensitive = false; + + if( !Call(item.functions[1], stream_temp2, true) ) return; + + if( !last_case_sensitive ) + case_sensitive = false; - MakeTextIf_go(item, info_res1 == info_res2); + bool res = AreStreamsEqual(stream_temp1, stream_temp2, case_sensitive); + + if( !equal ) + res = !res; + + MakeTextIf_go(item, res); } + +template +void Generator::MakeTextIs(Item & item) +{ + MakeTextIs(item, true); +} + + + template void Generator::MakeTextIsno(Item & item) { -bool info_res1, info_res2; - - if( item.functions.size() != 2 ) - return; - - if( !Call(item.functions[0], &info_res1) ) - return; - - if( !Call(item.functions[1], &info_res2) ) - return; - - MakeTextIf_go(item, info_res1 != info_res2); + MakeTextIs(item, false); } @@ -965,8 +1039,6 @@ void Generator::MakeTextIfindex(Item & item) template void Generator::MakeTextForLoop(Item & item, typename Functions::Function * function) { -bool info_res; - for( ; !break_generating ; stack_tab.back().iter += 1 ) { if( stack_tab.back().iter >= max_for_items ) @@ -976,9 +1048,9 @@ bool info_res; break; } - Call(function, item.functions[0].params, &info_res); + Call(function, item.functions[0].params, stream_temp1, true, empty_stream); - if( !info_res ) + if( !last_res ) break; if( !item.item_tab.empty() ) @@ -1074,7 +1146,7 @@ void Generator::MakeTextFilter(Item & item) if( !item.item_tab.empty() ) MakeText( *item.item_tab[0] ); // should be only one item - item_container - Call(function, item.functions[0].params, *old_stream, *output_stream); + Call(function, item.functions[0].params, *old_stream, false, *output_stream); output_stream = old_stream; filter_index -= 1; diff --git a/src/item.cpp b/src/item.cpp index d1730a6..b748026 100755 --- a/src/item.cpp +++ b/src/item.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2007-2010, Tomasz Sowa + * Copyright (c) 2007-2011, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without