added: Pattern::CacheFunctions(Functions<StreamType> & fun)
you can cache all functions (their addresses) in the pattern
changed: now we have two methods for generating content:
Generator<>::Generate(StreamType & o, Pattern & p, Functions<StreamType> & f);
similar like previous -- Set(...) methods were removed as well as the second ctor
and a second one:
Generate(StreamType & o, Pattern & p);
without functions, the functions should be cached beforehand in the pattern
by calling CacheFunctions() method on the pattern
this gives O(1) complexity when looking for a specific function
previously was O(log n)
git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@329 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
+100
-106
@@ -48,8 +48,7 @@ namespace Ezc
|
||||
{
|
||||
/*
|
||||
StreamType
|
||||
we use method write where the content should not be escaped (html escaping)
|
||||
we use operator<< where the content can be escaped (such as error messages)
|
||||
we use only method write(const wchar_t * str, size_t len) from the stream
|
||||
*/
|
||||
template<class StreamType>
|
||||
class Generator
|
||||
@@ -57,12 +56,7 @@ class Generator
|
||||
public:
|
||||
|
||||
Generator();
|
||||
Generator(StreamType & o, Pattern & p, Functions<StreamType> & f);
|
||||
|
||||
void Set(StreamType & o, Pattern & p, Functions<StreamType> & f);
|
||||
void Set(StreamType & o);
|
||||
void Set(Pattern & p);
|
||||
void Set(Functions<StreamType> & f);
|
||||
void SetMax(int max_items_, int max_for_items_);
|
||||
|
||||
// recognizing some special characters in text patterns (item_text in Patterns)
|
||||
@@ -86,8 +80,12 @@ public:
|
||||
// default: false
|
||||
void SkipNewLine(bool skip);
|
||||
|
||||
// the main method for generating
|
||||
void Generate();
|
||||
// the main methods for generating
|
||||
void Generate(StreamType & o, Pattern & p, Functions<StreamType> & f);
|
||||
|
||||
// this method is used only if the pattern has cached functions
|
||||
void Generate(StreamType & o, Pattern & p);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -111,11 +109,10 @@ private:
|
||||
const std::wstring empty;
|
||||
|
||||
|
||||
bool Find(const std::wstring & key, typename Functions<StreamType>::Function ** function);
|
||||
bool Find(const Item::Function & item_fun, typename Functions<StreamType>::Function ** function);
|
||||
|
||||
void Call(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info);
|
||||
bool Call(const std::wstring & name, FunInfo<StreamType> & info, typename Functions<StreamType>::Function ** pfun = 0);
|
||||
bool Call(typename Item::Function & function, bool * info_res = 0, typename Functions<StreamType>::Function ** pfun = 0);
|
||||
bool Call(Item::Function & function, bool * info_res = 0, typename Functions<StreamType>::Function ** pfun = 0);
|
||||
|
||||
void CallUserFunction(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info);
|
||||
void CallVariable(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info);
|
||||
@@ -128,9 +125,10 @@ private:
|
||||
void SkipWhite(const wchar_t *& str);
|
||||
int StrToInt(const wchar_t * str, const wchar_t ** str_end);
|
||||
|
||||
void CreateMsg(StreamType & o, const wchar_t * type, const wchar_t * arg = 0);
|
||||
void CreateMsg(StreamType & o, const std::wstring & type, const std::wstring & arg);
|
||||
void CreateMsg(StreamType & o, const std::wstring & type);
|
||||
void CreateMsg(const wchar_t * type, const wchar_t * arg = 0);
|
||||
void CreateMsg(const std::wstring & type, const std::wstring & arg);
|
||||
void CreateMsg(const std::wstring & type);
|
||||
void CreateUnknownMsg(const std::wstring & fun);
|
||||
|
||||
void MakeTextIf_go(Item & item, bool result);
|
||||
bool MakeTextIfindexnumber(Item & item, typename Functions<StreamType>::Function * function, bool & result);
|
||||
@@ -173,49 +171,6 @@ Generator<StreamType>::Generator()
|
||||
}
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
Generator<StreamType>::Generator(StreamType & o, Pattern & p, Functions<StreamType> & f)
|
||||
{
|
||||
output_stream = &o;
|
||||
pattern = &p;
|
||||
functions = &f;
|
||||
|
||||
max_items = 50000;
|
||||
max_for_items = 5000;
|
||||
special_chars = false;
|
||||
trim_white = false;
|
||||
skip_new_line = false;
|
||||
}
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::Set(StreamType & o, Pattern & p, Functions<StreamType> & f)
|
||||
{
|
||||
output_stream = &o;
|
||||
pattern = &p;
|
||||
functions = &f;
|
||||
}
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::Set(StreamType & o)
|
||||
{
|
||||
output_stream = &o;
|
||||
}
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::Set(Pattern & p)
|
||||
{
|
||||
pattern = &p;
|
||||
}
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::Set(Functions<StreamType> & f)
|
||||
{
|
||||
functions = &f;
|
||||
}
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
@@ -248,10 +203,25 @@ void Generator<StreamType>::SkipNewLine(bool skip)
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::Generate()
|
||||
void Generator<StreamType>::Generate(StreamType & o, Pattern & p, Functions<StreamType> & f)
|
||||
{
|
||||
if( !output_stream || !pattern || !functions )
|
||||
return;
|
||||
output_stream = &o;
|
||||
pattern = &p;
|
||||
functions = &f;
|
||||
|
||||
break_generating = false;
|
||||
current_item = 0;
|
||||
|
||||
MakeText( pattern->item_root );
|
||||
}
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::Generate(StreamType & o, Pattern & p)
|
||||
{
|
||||
output_stream = &o;
|
||||
pattern = &p;
|
||||
functions = 0;
|
||||
|
||||
break_generating = false;
|
||||
current_item = 0;
|
||||
@@ -263,12 +233,27 @@ void Generator<StreamType>::Generate()
|
||||
|
||||
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
bool Generator<StreamType>::Find(const std::wstring & key, typename Functions<StreamType>::Function ** function)
|
||||
bool Generator<StreamType>::Find(const Item::Function & item_fun, typename Functions<StreamType>::Function ** function)
|
||||
{
|
||||
if( !functions->Find(key, function) )
|
||||
if( !functions )
|
||||
{
|
||||
CreateMsg(*output_stream, L"can't find", key.c_str() );
|
||||
if( item_fun.fun_cache )
|
||||
{
|
||||
*function = reinterpret_cast<typename Functions<StreamType>::Function*>(item_fun.fun_cache);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateUnknownMsg(item_fun.name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if( !functions->Find(item_fun.name, function) )
|
||||
{
|
||||
CreateUnknownMsg(item_fun.name);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -276,14 +261,13 @@ return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::CallUserFunction(typename Functions<StreamType>::Function * function, FunInfo<StreamType> & info)
|
||||
{
|
||||
if( function->is_running )
|
||||
{
|
||||
// recurrences are not allowed
|
||||
CreateMsg(*output_stream, L"the function is being executed");
|
||||
CreateMsg(L"the function is being executed");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -315,53 +299,52 @@ void Generator<StreamType>::Call(typename Functions<StreamType>::Function * func
|
||||
}
|
||||
|
||||
|
||||
// return: true if a function or variable was found and called
|
||||
template<class StreamType>
|
||||
bool Generator<StreamType>::Call(const std::wstring & name, FunInfo<StreamType> & info, typename Functions<StreamType>::Function ** pfun)
|
||||
{
|
||||
typename Functions<StreamType>::Function * function;
|
||||
|
||||
if( Find(name, &function) )
|
||||
{
|
||||
Call(function, info);
|
||||
|
||||
if( pfun )
|
||||
*pfun = function;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// return: true if a function or variable was found and called
|
||||
template<class StreamType>
|
||||
bool Generator<StreamType>::Call(typename Item::Function & function, bool * info_res, typename Functions<StreamType>::Function ** pfun)
|
||||
bool Generator<StreamType>::Call(Item::Function & item_fun, bool * info_res, typename Functions<StreamType>::Function ** pfun)
|
||||
{
|
||||
bool called;
|
||||
typename Functions<StreamType>::Function * fun;
|
||||
bool called = false;
|
||||
|
||||
if( function.params.empty() )
|
||||
if( item_fun.params.empty() )
|
||||
{
|
||||
FunInfo<StreamType> info(*output_stream, function.params, empty);
|
||||
called = Call(function.name, info, pfun);
|
||||
FunInfo<StreamType> info(*output_stream, item_fun.params, empty);
|
||||
|
||||
if( Find(item_fun, &fun) )
|
||||
{
|
||||
Call(fun, info);
|
||||
called = true;
|
||||
}
|
||||
|
||||
if( info_res )
|
||||
*info_res = info.res;
|
||||
}
|
||||
else
|
||||
{
|
||||
FunInfo<StreamType> info(*output_stream, function.params, function.params[0]);
|
||||
called = Call(function.name, info, pfun);
|
||||
FunInfo<StreamType> info(*output_stream, item_fun.params, item_fun.params[0]);
|
||||
|
||||
if( Find(item_fun, &fun) )
|
||||
{
|
||||
Call(fun, info);
|
||||
called = true;
|
||||
}
|
||||
|
||||
if( info_res )
|
||||
*info_res = info.res;
|
||||
}
|
||||
|
||||
if( called && pfun )
|
||||
*pfun = fun;
|
||||
|
||||
return called;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
wchar_t Generator<StreamType>::CreateSpecialChar(wchar_t c)
|
||||
{
|
||||
@@ -520,30 +503,35 @@ return res;
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::CreateMsg(StreamType & o, const wchar_t * type, const wchar_t * arg)
|
||||
void Generator<StreamType>::CreateMsg(const wchar_t * type, const wchar_t * arg)
|
||||
{
|
||||
pattern->CreateMsg(temp_msg, type, arg);
|
||||
o << temp_msg;
|
||||
temp_msg.clear();
|
||||
output_stream->write(temp_msg.c_str(), temp_msg.size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::CreateMsg(StreamType & o, const std::wstring & type, const std::wstring & arg)
|
||||
void Generator<StreamType>::CreateMsg(const std::wstring & type, const std::wstring & arg)
|
||||
{
|
||||
CreateMsg(o, type.c_str(), arg.c_str());
|
||||
CreateMsg(type.c_str(), arg.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::CreateMsg(StreamType & o, const std::wstring & type)
|
||||
void Generator<StreamType>::CreateMsg(const std::wstring & type)
|
||||
{
|
||||
CreateMsg(o, type.c_str());
|
||||
CreateMsg(type.c_str());
|
||||
}
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::CreateUnknownMsg(const std::wstring & fun)
|
||||
{
|
||||
CreateMsg(L"unknown function", fun.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -770,7 +758,7 @@ bool Generator<StreamType>::MakeTextIfindexnumber(Item & item, typename Function
|
||||
|
||||
if( *last_char != '\0' )
|
||||
{
|
||||
CreateMsg(*output_stream, L"if-index: syntax error");
|
||||
CreateMsg(L"if-index: syntax error");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -792,7 +780,7 @@ void Generator<StreamType>::MakeTextIfindex(Item & item)
|
||||
|
||||
typename Functions<StreamType>::Function * function;
|
||||
|
||||
if( !Find(item.functions[0].name, &function) )
|
||||
if( !Find(item.functions[0], &function) )
|
||||
return;
|
||||
|
||||
bool result = false;
|
||||
@@ -832,7 +820,7 @@ bool info_res;
|
||||
{
|
||||
if( function->iter >= max_for_items )
|
||||
{
|
||||
CreateMsg(*output_stream, item.functions[0].name.c_str(),
|
||||
CreateMsg(item.functions[0].name.c_str(),
|
||||
L"function exceeded a limit for a [for] statement");
|
||||
break;
|
||||
}
|
||||
@@ -856,12 +844,12 @@ void Generator<StreamType>::MakeTextFor(Item & item)
|
||||
|
||||
typename Functions<StreamType>::Function * function;
|
||||
|
||||
if( !Find(item.functions[0].name, &function) )
|
||||
if( !Find(item.functions[0], &function) )
|
||||
return;
|
||||
|
||||
if( function->is_for )
|
||||
{
|
||||
CreateMsg(*output_stream, item.functions[0].name.c_str(),
|
||||
CreateMsg(item.functions[0].name.c_str(),
|
||||
L"this function is already used in a [for] statement");
|
||||
return;
|
||||
}
|
||||
@@ -880,6 +868,12 @@ void Generator<StreamType>::MakeTextFor(Item & item)
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::MakeTextDefine(Item & item)
|
||||
{
|
||||
if( !functions )
|
||||
{
|
||||
CreateMsg(L"def statement is not available when used without functions set");
|
||||
return;
|
||||
}
|
||||
|
||||
if( item.functions.size() == 1 )
|
||||
{
|
||||
// inserting a new variable
|
||||
@@ -891,7 +885,7 @@ void Generator<StreamType>::MakeTextDefine(Item & item)
|
||||
{
|
||||
typename Functions<StreamType>::Function * function;
|
||||
|
||||
if( Find(item.functions[1].name, &function) )
|
||||
if( Find(item.functions[1], &function) )
|
||||
{
|
||||
if( function->type == Functions<StreamType>::function )
|
||||
{
|
||||
@@ -919,7 +913,7 @@ void Generator<StreamType>::MakeText(Item & item)
|
||||
if( ++current_item > max_items )
|
||||
{
|
||||
break_generating = true;
|
||||
CreateMsg(*output_stream, L"Generator exceeded allowed number of elements");
|
||||
CreateMsg(L"Generator exceeded allowed number of elements");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -938,7 +932,7 @@ void Generator<StreamType>::MakeText(Item & item)
|
||||
else if( item.type == Item::item_for ) MakeTextFor(item);
|
||||
else if( item.type == Item::item_def ) MakeTextDefine(item);
|
||||
else if( item.type == Item::item_err )
|
||||
CreateMsg(*output_stream, L"a wrong directive");
|
||||
CreateMsg(L"a wrong directive");
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user