changed: [ezc streams "..."] to [ezc out "..."] or just [out "..."]
the syntax has been changed, now [ezc ...] is used with [end] statement added: OutStreams<StreamType> class with a pool with output streams, the Generator::Generate() method can take it as its argument (Generator API has been changed) git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@1014 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
parent
76490d4c19
commit
7b6f7ad328
352
src/generator.h
352
src/generator.h
|
@ -43,6 +43,7 @@
|
||||||
#include "pattern.h"
|
#include "pattern.h"
|
||||||
#include "functions.h"
|
#include "functions.h"
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
|
#include "outstreams.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -102,12 +103,6 @@ public:
|
||||||
// default stack size: 300
|
// default stack size: 300
|
||||||
void SetStackSize(size_t new_stack_size);
|
void SetStackSize(size_t new_stack_size);
|
||||||
|
|
||||||
// do not print anything to stream stream_index
|
|
||||||
// useful when using Generate() method with StreamType tables
|
|
||||||
// this is a small optimization if we know that a stream with stream_index will not be used later
|
|
||||||
// set stream_index to -1 to turn off (default)
|
|
||||||
void SkipStream(int stream_index);
|
|
||||||
|
|
||||||
// set whether or not we can use cache for functions or blocks
|
// set whether or not we can use cache for functions or blocks
|
||||||
// true by default
|
// true by default
|
||||||
void CanUseCache(bool can_use_cache);
|
void CanUseCache(bool can_use_cache);
|
||||||
|
@ -117,9 +112,10 @@ public:
|
||||||
void CanUseVars(bool can_use_variables);
|
void CanUseVars(bool can_use_variables);
|
||||||
|
|
||||||
// the main methods for generating
|
// the main methods for generating
|
||||||
void Generate(StreamType & o);
|
void Generate(StreamType & out);
|
||||||
void Generate(std::vector<StreamType> & o);
|
void Generate(StreamType & out, OutStreams<StreamType> & out_streams);
|
||||||
void Generate(std::vector<StreamType*> & o);
|
void Generate(OutStreams<StreamType> & out_streams);
|
||||||
|
|
||||||
|
|
||||||
void SetCommentary(const char * com_start, const char * com_stop);
|
void SetCommentary(const char * com_start, const char * com_stop);
|
||||||
void SetCommentary(const std::string & com_start, const std::string & com_stop);
|
void SetCommentary(const std::string & com_start, const std::string & com_stop);
|
||||||
|
@ -145,14 +141,8 @@ private:
|
||||||
size_t block_stack_index;
|
size_t block_stack_index;
|
||||||
size_t block_stack_size;
|
size_t block_stack_size;
|
||||||
|
|
||||||
// current output stream
|
// current output stream (can be null)
|
||||||
// if we are printing only to one stream e.g. [ezc output "3"]
|
// at the beginning it is pointing to the main stream (to the StreamType argument passsed to Generate method)
|
||||||
// then output_stream is pointing directly to that stream
|
|
||||||
// but if we are printing to more than one stream e.g. [ezc output "0" "2" "5"]
|
|
||||||
// then output_stream is pointing to output_tmp_stream and at the end
|
|
||||||
// output_tmp_stream is copied to the correct streams
|
|
||||||
// output_stream can be null e.g. [ezc output] without arguments
|
|
||||||
// in such a case we do not print anything (but any functions are evaluated)
|
|
||||||
StreamType * output_stream;
|
StreamType * output_stream;
|
||||||
|
|
||||||
Pattern * ppattern;
|
Pattern * ppattern;
|
||||||
|
@ -160,23 +150,9 @@ private:
|
||||||
Functions<StreamType> * pfunctions;
|
Functions<StreamType> * pfunctions;
|
||||||
Objects<StreamType> * pobjects;
|
Objects<StreamType> * pobjects;
|
||||||
|
|
||||||
// output_tmp_stream is used when outputting to more than one stream
|
// pointer to the output streams map (can be null)
|
||||||
// (first we output to output_tmp_stream and then the content is copied
|
// output stream will be created when [ezc out "stream_name"] statement is found
|
||||||
// to the correct streams)
|
OutStreams<StreamType> * output_stream_map;
|
||||||
StreamType output_tmp_stream;
|
|
||||||
|
|
||||||
// pointers to the output streams
|
|
||||||
std::vector<StreamType*> output_stream_tab;
|
|
||||||
|
|
||||||
// indices to output_stream_tab
|
|
||||||
// they are set by [put stream ...] keyword
|
|
||||||
// at the beginning there is only one index created automatically - "0"
|
|
||||||
std::vector<size_t> output_stream_index;
|
|
||||||
|
|
||||||
// if has_skip_stream_index is true then when reading stream indices from [put stream ...]
|
|
||||||
// a stream with skip_stream_index index will be ignored
|
|
||||||
bool has_skip_stream_index;
|
|
||||||
size_t skip_stream_index;
|
|
||||||
|
|
||||||
// temporary error messages
|
// temporary error messages
|
||||||
std::wstring temp_msg;
|
std::wstring temp_msg;
|
||||||
|
@ -189,6 +165,9 @@ private:
|
||||||
bool trim_white;
|
bool trim_white;
|
||||||
bool skip_new_line;
|
bool skip_new_line;
|
||||||
|
|
||||||
|
size_t ezc_out_stack_index;
|
||||||
|
size_t ezc_out_stack_size;
|
||||||
|
|
||||||
size_t stack_index;
|
size_t stack_index;
|
||||||
size_t stack_size;
|
size_t stack_size;
|
||||||
|
|
||||||
|
@ -197,6 +176,7 @@ private:
|
||||||
// we have to use a pointers table because standard streams such
|
// we have to use a pointers table because standard streams such
|
||||||
// as std::wostringstream are not copyable
|
// as std::wostringstream are not copyable
|
||||||
std::vector<StreamType*> filter_tab;
|
std::vector<StreamType*> filter_tab;
|
||||||
|
std::vector<StreamType*> ezc_out_stack_tab;
|
||||||
const StreamType empty_stream;
|
const StreamType empty_stream;
|
||||||
|
|
||||||
// used in [0] [1] [2] when there is no such argument defined
|
// used in [0] [1] [2] when there is no such argument defined
|
||||||
|
@ -230,13 +210,17 @@ private:
|
||||||
bool can_use_vars;
|
bool can_use_vars;
|
||||||
bool can_find_in_cache;
|
bool can_find_in_cache;
|
||||||
|
|
||||||
|
void ResizeStreamStack(std::vector<StreamType*> & stream_tab, size_t stream_tab_max_size);
|
||||||
void ResizeFilterTab();
|
void ResizeFilterTab();
|
||||||
void ResizeStack();
|
void ResizeStack();
|
||||||
void ResizeBlockStack();
|
void ResizeBlockStack();
|
||||||
|
void ResizeEzcOutStack();
|
||||||
|
|
||||||
|
void ClearStreamStack(std::vector<StreamType*> & stream_tab);
|
||||||
void ClearFilterTab();
|
void ClearFilterTab();
|
||||||
void ClearForStack();
|
void ClearForStack();
|
||||||
void ClearBlockStack();
|
void ClearBlockStack();
|
||||||
|
void ClearEzcOutTab();
|
||||||
|
|
||||||
void ClearStream(StreamType & str);
|
void ClearStream(StreamType & str);
|
||||||
void RemoveStackFunData(Stack & sitem);
|
void RemoveStackFunData(Stack & sitem);
|
||||||
|
@ -312,8 +296,9 @@ private:
|
||||||
size_t StrToSize(const wchar_t * str, const wchar_t ** str_end = 0);
|
size_t StrToSize(const wchar_t * str, const wchar_t ** str_end = 0);
|
||||||
|
|
||||||
|
|
||||||
void WriteTmpStreamToStreams();
|
void CopyTmpStreamToOutputStreams(Item::Function & fun, StreamType & ezc_out_tmp_stream, StreamType & previous_stream);
|
||||||
void CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t * arg = 0);
|
void CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t * arg = 0);
|
||||||
|
void CreateMsg(StreamType & stream, const wchar_t * type, const wchar_t * arg = 0);
|
||||||
void CreateMsg(const wchar_t * type, const wchar_t * arg = 0);
|
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, const std::wstring & arg);
|
||||||
void CreateMsg(const std::wstring & type);
|
void CreateMsg(const std::wstring & type);
|
||||||
|
@ -331,8 +316,7 @@ private:
|
||||||
void MakeTextEzc(Item & item);
|
void MakeTextEzc(Item & item);
|
||||||
void MakeTextReturn(Item & item);
|
void MakeTextReturn(Item & item);
|
||||||
void MakeText(Item & item);
|
void MakeText(Item & item);
|
||||||
|
void MakeEzcOut(Item & item);
|
||||||
void MakeEzcStream(Item::Function & fun);
|
|
||||||
|
|
||||||
void Generate();
|
void Generate();
|
||||||
|
|
||||||
|
@ -348,7 +332,6 @@ private:
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
Generator<StreamType>::Generator() : empty_stream()
|
Generator<StreamType>::Generator() : empty_stream()
|
||||||
{
|
{
|
||||||
output_stream = 0;
|
|
||||||
ppattern = 0;
|
ppattern = 0;
|
||||||
pblocks = 0;
|
pblocks = 0;
|
||||||
pfunctions = 0;
|
pfunctions = 0;
|
||||||
|
@ -363,7 +346,7 @@ Generator<StreamType>::Generator() : empty_stream()
|
||||||
is_generator_working = false;
|
is_generator_working = false;
|
||||||
stack_size = 300;
|
stack_size = 300;
|
||||||
block_stack_size = 64;
|
block_stack_size = 64;
|
||||||
has_skip_stream_index = false;
|
ezc_out_stack_size = 16;
|
||||||
can_find_in_cache = true;
|
can_find_in_cache = true;
|
||||||
can_use_vars = true;
|
can_use_vars = true;
|
||||||
}
|
}
|
||||||
|
@ -380,12 +363,6 @@ Generator<StreamType>::Generator(const Generator<StreamType> & n)
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
Generator<StreamType> & Generator<StreamType>::operator=(const Generator<StreamType> & n)
|
Generator<StreamType> & Generator<StreamType>::operator=(const Generator<StreamType> & n)
|
||||||
{
|
{
|
||||||
// !! CHECK ME may output_streams should not be copied?
|
|
||||||
output_stream_tab = n.output_stream_tab;
|
|
||||||
output_stream_index = n.output_stream_index;
|
|
||||||
output_tmp_stream = n.output_tmp_stream;
|
|
||||||
output_stream = n.output_stream;
|
|
||||||
|
|
||||||
ppattern = n.ppattern;
|
ppattern = n.ppattern;
|
||||||
pblocks = n.pblocks;
|
pblocks = n.pblocks;
|
||||||
pfunctions = n.pfunctions;
|
pfunctions = n.pfunctions;
|
||||||
|
@ -396,7 +373,6 @@ Generator<StreamType> & Generator<StreamType>::operator=(const Generator<StreamT
|
||||||
special_chars = n.special_chars;
|
special_chars = n.special_chars;
|
||||||
trim_white = n.trim_white;
|
trim_white = n.trim_white;
|
||||||
skip_new_line = n.skip_new_line;
|
skip_new_line = n.skip_new_line;
|
||||||
has_skip_stream_index = n.has_skip_stream_index;
|
|
||||||
can_find_in_cache = n.can_find_in_cache;
|
can_find_in_cache = n.can_find_in_cache;
|
||||||
can_use_vars = n.can_use_vars;
|
can_use_vars = n.can_use_vars;
|
||||||
|
|
||||||
|
@ -404,11 +380,14 @@ Generator<StreamType> & Generator<StreamType>::operator=(const Generator<StreamT
|
||||||
filter_size = n.filter_size;
|
filter_size = n.filter_size;
|
||||||
stack_size = n.stack_size;
|
stack_size = n.stack_size;
|
||||||
block_stack_size = n.block_stack_size;
|
block_stack_size = n.block_stack_size;
|
||||||
|
ezc_out_stack_size = n.ezc_out_stack_size;
|
||||||
|
|
||||||
// vars doesn't have to be copied
|
// vars doesn't have to be copied
|
||||||
|
|
||||||
// don't copy filter tab
|
// don't copy filter tab
|
||||||
// don't copy stack
|
// don't copy stack
|
||||||
|
// don't copy ezc_out_stack_tab
|
||||||
|
// don't copy output_stream and output_stream_map
|
||||||
|
|
||||||
// !! CHECK ME
|
// !! CHECK ME
|
||||||
// may copying should be denied when generator is working?
|
// may copying should be denied when generator is working?
|
||||||
|
@ -426,6 +405,7 @@ Generator<StreamType>::~Generator()
|
||||||
ClearFilterTab();
|
ClearFilterTab();
|
||||||
ClearForStack();
|
ClearForStack();
|
||||||
ClearBlockStack();
|
ClearBlockStack();
|
||||||
|
ClearEzcOutTab();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -509,26 +489,6 @@ void Generator<StreamType>::CanUseVars(bool can_use_variables)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
|
||||||
void Generator<StreamType>::ResizeFilterTab()
|
|
||||||
{
|
|
||||||
if( filter_tab.size() != filter_size )
|
|
||||||
{
|
|
||||||
if( filter_tab.size() < filter_size )
|
|
||||||
{
|
|
||||||
for(size_t i=filter_tab.size() ; i<filter_size ; ++i)
|
|
||||||
filter_tab.push_back( new StreamType() );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for(size_t i=filter_size ; i<filter_tab.size() ; ++i)
|
|
||||||
delete filter_tab[i];
|
|
||||||
|
|
||||||
filter_tab.resize(filter_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::ResizeStack()
|
void Generator<StreamType>::ResizeStack()
|
||||||
|
@ -546,6 +506,45 @@ void Generator<StreamType>::ResizeStack()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
void Generator<StreamType>::ResizeStreamStack(std::vector<StreamType*> & stream_tab, size_t stream_tab_max_size)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
void Generator<StreamType>::ResizeFilterTab()
|
||||||
|
{
|
||||||
|
ResizeStreamStack(filter_tab, filter_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
void Generator<StreamType>::ResizeEzcOutStack()
|
||||||
|
{
|
||||||
|
ResizeStreamStack(ezc_out_stack_tab, ezc_out_stack_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::ResizeBlockStack()
|
void Generator<StreamType>::ResizeBlockStack()
|
||||||
{
|
{
|
||||||
|
@ -570,13 +569,30 @@ void Generator<StreamType>::ResizeBlockStack()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
void Generator<StreamType>::ClearStreamStack(std::vector<StreamType*> & stream_tab)
|
||||||
|
{
|
||||||
|
for(size_t i=0 ; i<stream_tab.size() ; ++i)
|
||||||
|
delete stream_tab[i];
|
||||||
|
|
||||||
|
stream_tab.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::ClearFilterTab()
|
void Generator<StreamType>::ClearFilterTab()
|
||||||
{
|
{
|
||||||
for(size_t i=0 ; i<filter_tab.size() ; ++i)
|
ClearStreamStack(filter_tab);
|
||||||
delete filter_tab[i];
|
}
|
||||||
|
|
||||||
filter_tab.clear();
|
|
||||||
|
template<class StreamType>
|
||||||
|
void Generator<StreamType>::ClearEzcOutTab()
|
||||||
|
{
|
||||||
|
ClearStreamStack(ezc_out_stack_tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -620,22 +636,6 @@ void Generator<StreamType>::RemoveStackFunData(Stack & s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
|
||||||
void Generator<StreamType>::SkipStream(int stream_index)
|
|
||||||
{
|
|
||||||
if( stream_index < 0 )
|
|
||||||
{
|
|
||||||
has_skip_stream_index = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
has_skip_stream_index = true;
|
|
||||||
skip_stream_index = stream_index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
template<class CharType>
|
template<class CharType>
|
||||||
CharType Generator<StreamType>::ToLower(CharType c)
|
CharType Generator<StreamType>::ToLower(CharType c)
|
||||||
|
@ -712,19 +712,6 @@ void Generator<StreamType>::Generate()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
output_stream = 0;
|
|
||||||
output_stream_index.clear();
|
|
||||||
ClearStream(output_tmp_stream);
|
|
||||||
|
|
||||||
if( !output_stream_tab.empty() )
|
|
||||||
{
|
|
||||||
if( !has_skip_stream_index || skip_stream_index != 0 )
|
|
||||||
{
|
|
||||||
output_stream_index.push_back(0);
|
|
||||||
output_stream = output_stream_tab[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break_generating = false;
|
break_generating = false;
|
||||||
current_item = 0;
|
current_item = 0;
|
||||||
|
|
||||||
|
@ -736,6 +723,7 @@ void Generator<StreamType>::Generate()
|
||||||
ResizeFilterTab();
|
ResizeFilterTab();
|
||||||
ResizeStack();
|
ResizeStack();
|
||||||
ResizeBlockStack();
|
ResizeBlockStack();
|
||||||
|
ResizeEzcOutStack();
|
||||||
filter_index = 0;
|
filter_index = 0;
|
||||||
stack_index = 0;
|
stack_index = 0;
|
||||||
block_stack_index = 0;
|
block_stack_index = 0;
|
||||||
|
@ -747,10 +735,8 @@ void Generator<StreamType>::Generate()
|
||||||
{
|
{
|
||||||
is_generator_working = true;
|
is_generator_working = true;
|
||||||
MakeText( ppattern->item_root );
|
MakeText( ppattern->item_root );
|
||||||
|
// !! IMPROVE ME we can print an error message if the stacks are not empty
|
||||||
if( output_stream_index.size() > 1 )
|
// (some [end] statements has been omited)
|
||||||
WriteTmpStreamToStreams();
|
|
||||||
|
|
||||||
vars.clear();
|
vars.clear();
|
||||||
is_generator_working = false;
|
is_generator_working = false;
|
||||||
}
|
}
|
||||||
|
@ -764,36 +750,29 @@ void Generator<StreamType>::Generate()
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::Generate(StreamType & o)
|
void Generator<StreamType>::Generate(StreamType & out)
|
||||||
{
|
{
|
||||||
output_stream_tab.resize(1);
|
output_stream = &out;
|
||||||
output_stream_tab[0] = &o;
|
output_stream_map = 0;
|
||||||
|
|
||||||
Generate();
|
Generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::Generate(std::vector<StreamType> & o)
|
void Generator<StreamType>::Generate(StreamType & out, OutStreams<StreamType> & out_streams)
|
||||||
{
|
{
|
||||||
output_stream_tab.resize(o.size());
|
output_stream = &out;
|
||||||
|
output_stream_map = &out_streams;
|
||||||
for(size_t i=0 ; i<o.size() ; ++i)
|
|
||||||
output_stream_tab[i] = &o[i];
|
|
||||||
|
|
||||||
Generate();
|
Generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::Generate(std::vector<StreamType*> & o)
|
void Generator<StreamType>::Generate(OutStreams<StreamType> & out_streams)
|
||||||
{
|
{
|
||||||
output_stream_tab.resize(o.size());
|
output_stream = 0;
|
||||||
|
output_stream_map = &out_streams;
|
||||||
for(size_t i=0 ; i<o.size() ; ++i)
|
|
||||||
output_stream_tab[i] = o[i];
|
|
||||||
|
|
||||||
Generate();
|
Generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1332,26 +1311,48 @@ return res;
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::WriteTmpStreamToStreams()
|
void Generator<StreamType>::CopyTmpStreamToOutputStreams(Item::Function & fun, StreamType & ezc_out_tmp_stream, StreamType & previous_stream)
|
||||||
{
|
{
|
||||||
#ifdef EZC_HAS_SPECIAL_STREAM
|
if( output_stream_map )
|
||||||
const std::wstring & str = output_tmp_stream.Str();
|
|
||||||
#else
|
|
||||||
const std::wstring & str = output_tmp_stream.str();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
if( !str.empty() )
|
|
||||||
{
|
{
|
||||||
for(size_t s = 0 ; s < output_stream_index.size() ; ++s)
|
#ifdef EZC_HAS_SPECIAL_STREAM
|
||||||
|
const std::wstring & str = ezc_out_tmp_stream.Str();
|
||||||
|
#else
|
||||||
|
const std::wstring & str = ezc_out_tmp_stream.str();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( !str.empty() )
|
||||||
{
|
{
|
||||||
size_t i = output_stream_index[s];
|
previous_stream.write(str.c_str(), str.size());
|
||||||
|
|
||||||
if( i < output_stream_tab.size() )
|
for(size_t s=0 ; s < fun.parameters.size() ; ++s)
|
||||||
output_stream_tab[i]->write(str.c_str(), str.size());
|
{
|
||||||
|
std::wstring & name = fun.parameters[s]->name;
|
||||||
|
std::pair<OutStreams<StreamType>::StreamsMap::iterator, bool> iterator_inserted = output_stream_map->streams_map.insert(std::make_pair(name, (StreamType*)0));
|
||||||
|
|
||||||
|
StreamType * & stream = iterator_inserted.first->second;
|
||||||
|
bool inserted = iterator_inserted.second;
|
||||||
|
|
||||||
|
if( inserted )
|
||||||
|
{
|
||||||
|
if( output_stream_map->streams_map.size() <= output_stream_map->streams_tab.size() )
|
||||||
|
{
|
||||||
|
/* a new stream from the pool (output_stream_tab) has been taken */
|
||||||
|
stream = output_stream_map->streams_tab[ output_stream_map->streams_map.size() - 1 ];
|
||||||
|
ClearStream(*stream);
|
||||||
|
stream->write(str.c_str(), str.size());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CreateMsg(previous_stream, L"limit of output streams has been reached");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stream->write(str.c_str(), str.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ClearStream(output_tmp_stream);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1374,15 +1375,20 @@ void Generator<StreamType>::CreateMsg(std::wstring & out, const wchar_t * type,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
void Generator<StreamType>::CreateMsg(StreamType & stream, const wchar_t * type, const wchar_t * arg)
|
||||||
|
{
|
||||||
|
CreateMsg(temp_msg, type, arg);
|
||||||
|
stream.write(temp_msg.c_str(), temp_msg.size());
|
||||||
|
temp_msg.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::CreateMsg(const wchar_t * type, const wchar_t * arg)
|
void Generator<StreamType>::CreateMsg(const wchar_t * type, const wchar_t * arg)
|
||||||
{
|
{
|
||||||
if( output_stream )
|
if( output_stream )
|
||||||
{
|
CreateMsg(*output_stream, type, arg);
|
||||||
CreateMsg(temp_msg, type, arg);
|
|
||||||
output_stream->write(temp_msg.c_str(), temp_msg.size());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1598,53 +1604,61 @@ void Generator<StreamType>::MakeTextFilter(Item & item)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
although we are using a stack for [etc out] there is no need for the stack now
|
||||||
|
because the output is only a one-level map (not nested structure)
|
||||||
|
but in the future we can use more complicated class like PT::Space
|
||||||
|
and then nested [ezc out] statements can product a better output
|
||||||
|
*/
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::MakeEzcStream(Item::Function & fun)
|
void Generator<StreamType>::MakeEzcOut(Item & item)
|
||||||
{
|
{
|
||||||
if( output_stream_index.size() > 1 )
|
std::vector<std::wstring*> output_stream_names;
|
||||||
WriteTmpStreamToStreams();
|
StreamType * old_stream;
|
||||||
|
bool stream_added = true;
|
||||||
|
|
||||||
output_stream_index.clear();
|
if( ezc_out_stack_index >= ezc_out_stack_tab.size() )
|
||||||
|
|
||||||
for(size_t i=0 ; i<fun.parameters.size() ; ++i)
|
|
||||||
{
|
{
|
||||||
size_t index = StrToSize(fun.parameters[i]->name.c_str());
|
CreateMsg(L"Generator exceeded allowed number of [ezc out] statements");
|
||||||
|
return;
|
||||||
if( index < output_stream_tab.size() )
|
|
||||||
{
|
|
||||||
if( !has_skip_stream_index || skip_stream_index != index )
|
|
||||||
output_stream_index.push_back(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// we do not print any information if the index is out of range
|
|
||||||
// because we do not know to which stream is should be printed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( output_stream_index.size() > 1 )
|
/*
|
||||||
|
if we encounter the first ezc_out statement without arguments e.g. [ezc out] or just [out]
|
||||||
|
then we can simply ignore it
|
||||||
|
*/
|
||||||
|
if( item.function.parameters.empty() && ezc_out_stack_index == 0 )
|
||||||
|
stream_added = false;
|
||||||
|
|
||||||
|
if( stream_added )
|
||||||
{
|
{
|
||||||
ClearStream(output_tmp_stream);
|
old_stream = output_stream;
|
||||||
output_stream = &output_tmp_stream;
|
output_stream = ezc_out_stack_tab[ezc_out_stack_index];
|
||||||
|
ClearStream(*output_stream);
|
||||||
|
ezc_out_stack_index += 1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
if( output_stream_index.size() == 1 )
|
if( !item.item_tab.empty() )
|
||||||
|
MakeText( *item.item_tab[0] ); // should be only one item - item_container
|
||||||
|
|
||||||
|
if( stream_added )
|
||||||
{
|
{
|
||||||
size_t index = output_stream_index[0];
|
CopyTmpStreamToOutputStreams(item.function, *output_stream, *old_stream);
|
||||||
output_stream = output_stream_tab[index];
|
ClearStream(*output_stream);
|
||||||
}
|
output_stream = old_stream;
|
||||||
else
|
ezc_out_stack_index -= 1;
|
||||||
{
|
|
||||||
output_stream = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class StreamType>
|
template<class StreamType>
|
||||||
void Generator<StreamType>::MakeTextEzc(Item & item)
|
void Generator<StreamType>::MakeTextEzc(Item & item)
|
||||||
{
|
{
|
||||||
if( item.function.name == L"stream" )
|
if( item.function.name == L"out" )
|
||||||
MakeEzcStream(item.function);
|
MakeEzcOut(item);
|
||||||
else
|
|
||||||
CreateMsg(L"incorrect argument to [ezc] statement");
|
|
||||||
|
|
||||||
// in the future we can use more builtin functions
|
// in the future we can use more builtin functions
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,171 @@
|
||||||
|
/*
|
||||||
|
* This file is a part of EZC -- Easy templating in C++ library
|
||||||
|
* and is distributed under the BSD 3-Clause licence.
|
||||||
|
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Tomasz Sowa
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||||
|
* project may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef headerfile_ezc_outstreams
|
||||||
|
#define headerfile_ezc_outstreams
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
|
namespace Ezc
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
class OutStreams
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::map<std::wstring, StreamType*> StreamsMap; // can have null pointers
|
||||||
|
typedef std::vector<StreamType*> StreamsTab;
|
||||||
|
|
||||||
|
StreamsMap streams_map;
|
||||||
|
StreamsTab streams_tab;
|
||||||
|
|
||||||
|
void ResizeTab(size_t len);
|
||||||
|
|
||||||
|
void ClearMap();
|
||||||
|
void ClearTab();
|
||||||
|
|
||||||
|
~OutStreams();
|
||||||
|
OutStreams();
|
||||||
|
OutStreams(const OutStreams<StreamType> & o);
|
||||||
|
OutStreams<StreamType> & operator=(const OutStreams<StreamType> & o);
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
OutStreams<StreamType>::~OutStreams()
|
||||||
|
{
|
||||||
|
ClearTab();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
OutStreams<StreamType>::OutStreams()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
OutStreams<StreamType>::OutStreams(const OutStreams<StreamType> & o)
|
||||||
|
{
|
||||||
|
// we do not copy streams but creating new ones
|
||||||
|
ResizeTab(o.streams_tab.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
OutStreams<StreamType> & OutStreams<StreamType>::operator=(const OutStreams<StreamType> & o)
|
||||||
|
{
|
||||||
|
// we do not copy streams but creating new ones
|
||||||
|
streams_map.clear();
|
||||||
|
ResizeTab(o.streams_tab.size());
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
void OutStreams<StreamType>::ClearTab()
|
||||||
|
{
|
||||||
|
for(size_t i=0 ; i<streams_tab.size() ; ++i)
|
||||||
|
delete streams_tab[i];
|
||||||
|
|
||||||
|
streams_tab.clear();
|
||||||
|
streams_map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
void OutStreams<StreamType>::ResizeTab(size_t len)
|
||||||
|
{
|
||||||
|
if( streams_tab.size() != len )
|
||||||
|
{
|
||||||
|
if( streams_tab.size() < len )
|
||||||
|
{
|
||||||
|
size_t i = streams_tab.size();
|
||||||
|
streams_tab.resize(len);
|
||||||
|
|
||||||
|
for( ; i<streams_tab.size() ; ++i)
|
||||||
|
streams_tab[i] = new StreamType();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
streams_map.clear();
|
||||||
|
|
||||||
|
for(size_t i=len ; i<streams_tab.size() ; ++i)
|
||||||
|
delete streams_tab[i];
|
||||||
|
|
||||||
|
streams_tab.resize(len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class StreamType>
|
||||||
|
void OutStreams<StreamType>::ClearMap()
|
||||||
|
{
|
||||||
|
StreamsMap::iterator i;
|
||||||
|
|
||||||
|
for(i=streams_map.begin() ; i != streams_map.end() ; ++i)
|
||||||
|
{
|
||||||
|
StreamType & str = *(i->second);
|
||||||
|
|
||||||
|
#ifdef EZC_HAS_SPECIAL_STREAM
|
||||||
|
str.Clear();
|
||||||
|
#else
|
||||||
|
str.str(L"");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
streams_map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
#endif
|
|
@ -791,6 +791,26 @@ void PatternParser::ReadDirectiveEzc(Item & item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
[out] is a shorthand for [ezc out]
|
||||||
|
*/
|
||||||
|
void PatternParser::ReadDirectiveOut(Item & item)
|
||||||
|
{
|
||||||
|
item.type = Item::item_ezc;
|
||||||
|
item.has_function = true;
|
||||||
|
|
||||||
|
item.function.Clear();
|
||||||
|
item.function.name = L"out";
|
||||||
|
item.function.is_function = true;
|
||||||
|
|
||||||
|
if( !ReadParams(item.function) )
|
||||||
|
{
|
||||||
|
item.type = Item::item_err;
|
||||||
|
item.function.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PatternParser::ReadDirectiveBlock(Item & item)
|
void PatternParser::ReadDirectiveBlock(Item & item)
|
||||||
{
|
{
|
||||||
item.type = Item::item_block;
|
item.type = Item::item_block;
|
||||||
|
@ -827,6 +847,7 @@ std::wstring name;
|
||||||
else if( name == L"def" ) ReadDirectiveDef(item);
|
else if( name == L"def" ) ReadDirectiveDef(item);
|
||||||
else if( name == L"filter" ) ReadDirectiveFilter(item);
|
else if( name == L"filter" ) ReadDirectiveFilter(item);
|
||||||
else if( name == L"ezc" ) ReadDirectiveEzc(item);
|
else if( name == L"ezc" ) ReadDirectiveEzc(item);
|
||||||
|
else if( name == L"out" ) ReadDirectiveOut(item);
|
||||||
else if( name == L"block" ) ReadDirectiveBlock(item);
|
else if( name == L"block" ) ReadDirectiveBlock(item);
|
||||||
else if( name == L"return" ) ReadDirectiveReturn(item);
|
else if( name == L"return" ) ReadDirectiveReturn(item);
|
||||||
else if( name == L"#" ) ReadDirectiveComment(item);
|
else if( name == L"#" ) ReadDirectiveComment(item);
|
||||||
|
@ -990,7 +1011,8 @@ void PatternParser::CreateTree(Item & item)
|
||||||
CreateTreeReadIf(*pitem);
|
CreateTreeReadIf(*pitem);
|
||||||
|
|
||||||
if( pitem->type == Item::item_for ||
|
if( pitem->type == Item::item_for ||
|
||||||
pitem->type == Item::item_filter )
|
pitem->type == Item::item_filter ||
|
||||||
|
pitem->type == Item::item_ezc )
|
||||||
CreateTreeReadFor(*pitem);
|
CreateTreeReadFor(*pitem);
|
||||||
|
|
||||||
if( pitem->type == Item::item_include )
|
if( pitem->type == Item::item_include )
|
||||||
|
|
|
@ -172,6 +172,7 @@ private:
|
||||||
void ReadDirectiveDef(Item & item);
|
void ReadDirectiveDef(Item & item);
|
||||||
void ReadDirectiveFilter(Item & item);
|
void ReadDirectiveFilter(Item & item);
|
||||||
void ReadDirectiveEzc(Item & item);
|
void ReadDirectiveEzc(Item & item);
|
||||||
|
void ReadDirectiveOut(Item & item);
|
||||||
void ReadDirectiveBlock(Item & item);
|
void ReadDirectiveBlock(Item & item);
|
||||||
void ReadDirectiveReturn(Item & item);
|
void ReadDirectiveReturn(Item & item);
|
||||||
void ReadDirectiveNormal(const std::wstring & name, Item & item);
|
void ReadDirectiveNormal(const std::wstring & name, Item & item);
|
||||||
|
|
Loading…
Reference in New Issue