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 "functions.h"
|
||||
#include "objects.h"
|
||||
#include "outstreams.h"
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
@ -102,12 +103,6 @@ public:
|
|||
// default stack size: 300
|
||||
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
|
||||
// true by default
|
||||
void CanUseCache(bool can_use_cache);
|
||||
|
@ -117,9 +112,10 @@ public:
|
|||
void CanUseVars(bool can_use_variables);
|
||||
|
||||
// the main methods for generating
|
||||
void Generate(StreamType & o);
|
||||
void Generate(std::vector<StreamType> & o);
|
||||
void Generate(std::vector<StreamType*> & o);
|
||||
void Generate(StreamType & out);
|
||||
void Generate(StreamType & out, OutStreams<StreamType> & out_streams);
|
||||
void Generate(OutStreams<StreamType> & out_streams);
|
||||
|
||||
|
||||
void SetCommentary(const char * com_start, const char * 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_size;
|
||||
|
||||
// current output stream
|
||||
// if we are printing only to one stream e.g. [ezc output "3"]
|
||||
// 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)
|
||||
// current output stream (can be null)
|
||||
// at the beginning it is pointing to the main stream (to the StreamType argument passsed to Generate method)
|
||||
StreamType * output_stream;
|
||||
|
||||
Pattern * ppattern;
|
||||
|
@ -160,23 +150,9 @@ private:
|
|||
Functions<StreamType> * pfunctions;
|
||||
Objects<StreamType> * pobjects;
|
||||
|
||||
// output_tmp_stream is used when outputting to more than one stream
|
||||
// (first we output to output_tmp_stream and then the content is copied
|
||||
// to the correct streams)
|
||||
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;
|
||||
// pointer to the output streams map (can be null)
|
||||
// output stream will be created when [ezc out "stream_name"] statement is found
|
||||
OutStreams<StreamType> * output_stream_map;
|
||||
|
||||
// temporary error messages
|
||||
std::wstring temp_msg;
|
||||
|
@ -189,6 +165,9 @@ private:
|
|||
bool trim_white;
|
||||
bool skip_new_line;
|
||||
|
||||
size_t ezc_out_stack_index;
|
||||
size_t ezc_out_stack_size;
|
||||
|
||||
size_t stack_index;
|
||||
size_t stack_size;
|
||||
|
||||
|
@ -197,6 +176,7 @@ private:
|
|||
// we have to use a pointers table because standard streams such
|
||||
// as std::wostringstream are not copyable
|
||||
std::vector<StreamType*> filter_tab;
|
||||
std::vector<StreamType*> ezc_out_stack_tab;
|
||||
const StreamType empty_stream;
|
||||
|
||||
// used in [0] [1] [2] when there is no such argument defined
|
||||
|
@ -230,13 +210,17 @@ private:
|
|||
bool can_use_vars;
|
||||
bool can_find_in_cache;
|
||||
|
||||
void ResizeStreamStack(std::vector<StreamType*> & stream_tab, size_t stream_tab_max_size);
|
||||
void ResizeFilterTab();
|
||||
void ResizeStack();
|
||||
void ResizeBlockStack();
|
||||
void ResizeEzcOutStack();
|
||||
|
||||
void ClearStreamStack(std::vector<StreamType*> & stream_tab);
|
||||
void ClearFilterTab();
|
||||
void ClearForStack();
|
||||
void ClearBlockStack();
|
||||
void ClearEzcOutTab();
|
||||
|
||||
void ClearStream(StreamType & str);
|
||||
void RemoveStackFunData(Stack & sitem);
|
||||
|
@ -312,8 +296,9 @@ private:
|
|||
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(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 std::wstring & type, const std::wstring & arg);
|
||||
void CreateMsg(const std::wstring & type);
|
||||
|
@ -331,8 +316,7 @@ private:
|
|||
void MakeTextEzc(Item & item);
|
||||
void MakeTextReturn(Item & item);
|
||||
void MakeText(Item & item);
|
||||
|
||||
void MakeEzcStream(Item::Function & fun);
|
||||
void MakeEzcOut(Item & item);
|
||||
|
||||
void Generate();
|
||||
|
||||
|
@ -348,7 +332,6 @@ private:
|
|||
template<class StreamType>
|
||||
Generator<StreamType>::Generator() : empty_stream()
|
||||
{
|
||||
output_stream = 0;
|
||||
ppattern = 0;
|
||||
pblocks = 0;
|
||||
pfunctions = 0;
|
||||
|
@ -363,7 +346,7 @@ Generator<StreamType>::Generator() : empty_stream()
|
|||
is_generator_working = false;
|
||||
stack_size = 300;
|
||||
block_stack_size = 64;
|
||||
has_skip_stream_index = false;
|
||||
ezc_out_stack_size = 16;
|
||||
can_find_in_cache = true;
|
||||
can_use_vars = true;
|
||||
}
|
||||
|
@ -380,12 +363,6 @@ Generator<StreamType>::Generator(const Generator<StreamType> & n)
|
|||
template<class StreamType>
|
||||
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;
|
||||
pblocks = n.pblocks;
|
||||
pfunctions = n.pfunctions;
|
||||
|
@ -396,7 +373,6 @@ Generator<StreamType> & Generator<StreamType>::operator=(const Generator<StreamT
|
|||
special_chars = n.special_chars;
|
||||
trim_white = n.trim_white;
|
||||
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_use_vars = n.can_use_vars;
|
||||
|
||||
|
@ -404,11 +380,14 @@ Generator<StreamType> & Generator<StreamType>::operator=(const Generator<StreamT
|
|||
filter_size = n.filter_size;
|
||||
stack_size = n.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
|
||||
|
||||
// don't copy filter tab
|
||||
// don't copy stack
|
||||
// don't copy ezc_out_stack_tab
|
||||
// don't copy output_stream and output_stream_map
|
||||
|
||||
// !! CHECK ME
|
||||
// may copying should be denied when generator is working?
|
||||
|
@ -426,6 +405,7 @@ Generator<StreamType>::~Generator()
|
|||
ClearFilterTab();
|
||||
ClearForStack();
|
||||
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>
|
||||
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>
|
||||
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>
|
||||
void Generator<StreamType>::ClearFilterTab()
|
||||
{
|
||||
for(size_t i=0 ; i<filter_tab.size() ; ++i)
|
||||
delete filter_tab[i];
|
||||
|
||||
filter_tab.clear();
|
||||
ClearStreamStack(filter_tab);
|
||||
}
|
||||
|
||||
|
||||
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 CharType>
|
||||
CharType Generator<StreamType>::ToLower(CharType c)
|
||||
|
@ -712,19 +712,6 @@ void Generator<StreamType>::Generate()
|
|||
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;
|
||||
current_item = 0;
|
||||
|
||||
|
@ -736,6 +723,7 @@ void Generator<StreamType>::Generate()
|
|||
ResizeFilterTab();
|
||||
ResizeStack();
|
||||
ResizeBlockStack();
|
||||
ResizeEzcOutStack();
|
||||
filter_index = 0;
|
||||
stack_index = 0;
|
||||
block_stack_index = 0;
|
||||
|
@ -747,10 +735,8 @@ void Generator<StreamType>::Generate()
|
|||
{
|
||||
is_generator_working = true;
|
||||
MakeText( ppattern->item_root );
|
||||
|
||||
if( output_stream_index.size() > 1 )
|
||||
WriteTmpStreamToStreams();
|
||||
|
||||
// !! IMPROVE ME we can print an error message if the stacks are not empty
|
||||
// (some [end] statements has been omited)
|
||||
vars.clear();
|
||||
is_generator_working = false;
|
||||
}
|
||||
|
@ -764,36 +750,29 @@ void Generator<StreamType>::Generate()
|
|||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::Generate(StreamType & o)
|
||||
void Generator<StreamType>::Generate(StreamType & out)
|
||||
{
|
||||
output_stream_tab.resize(1);
|
||||
output_stream_tab[0] = &o;
|
||||
|
||||
output_stream = &out;
|
||||
output_stream_map = 0;
|
||||
Generate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
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());
|
||||
|
||||
for(size_t i=0 ; i<o.size() ; ++i)
|
||||
output_stream_tab[i] = &o[i];
|
||||
|
||||
output_stream = &out;
|
||||
output_stream_map = &out_streams;
|
||||
Generate();
|
||||
}
|
||||
|
||||
|
||||
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());
|
||||
|
||||
for(size_t i=0 ; i<o.size() ; ++i)
|
||||
output_stream_tab[i] = o[i];
|
||||
|
||||
output_stream = 0;
|
||||
output_stream_map = &out_streams;
|
||||
Generate();
|
||||
}
|
||||
|
||||
|
@ -1332,26 +1311,48 @@ return res;
|
|||
|
||||
|
||||
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
|
||||
const std::wstring & str = output_tmp_stream.Str();
|
||||
#else
|
||||
const std::wstring & str = output_tmp_stream.str();
|
||||
#endif
|
||||
|
||||
|
||||
if( !str.empty() )
|
||||
if( output_stream_map )
|
||||
{
|
||||
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() )
|
||||
output_stream_tab[i]->write(str.c_str(), str.size());
|
||||
for(size_t s=0 ; s < fun.parameters.size() ; ++s)
|
||||
{
|
||||
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>
|
||||
void Generator<StreamType>::CreateMsg(const wchar_t * type, const wchar_t * arg)
|
||||
{
|
||||
if( output_stream )
|
||||
{
|
||||
CreateMsg(temp_msg, type, arg);
|
||||
output_stream->write(temp_msg.c_str(), temp_msg.size());
|
||||
}
|
||||
CreateMsg(*output_stream, type, arg);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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>
|
||||
void Generator<StreamType>::MakeEzcStream(Item::Function & fun)
|
||||
void Generator<StreamType>::MakeEzcOut(Item & item)
|
||||
{
|
||||
if( output_stream_index.size() > 1 )
|
||||
WriteTmpStreamToStreams();
|
||||
std::vector<std::wstring*> output_stream_names;
|
||||
StreamType * old_stream;
|
||||
bool stream_added = true;
|
||||
|
||||
output_stream_index.clear();
|
||||
|
||||
for(size_t i=0 ; i<fun.parameters.size() ; ++i)
|
||||
if( ezc_out_stack_index >= ezc_out_stack_tab.size() )
|
||||
{
|
||||
size_t index = StrToSize(fun.parameters[i]->name.c_str());
|
||||
|
||||
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
|
||||
CreateMsg(L"Generator exceeded allowed number of [ezc out] statements");
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
output_stream = &output_tmp_stream;
|
||||
old_stream = output_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];
|
||||
output_stream = output_stream_tab[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
output_stream = 0;
|
||||
CopyTmpStreamToOutputStreams(item.function, *output_stream, *old_stream);
|
||||
ClearStream(*output_stream);
|
||||
output_stream = old_stream;
|
||||
ezc_out_stack_index -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class StreamType>
|
||||
void Generator<StreamType>::MakeTextEzc(Item & item)
|
||||
{
|
||||
if( item.function.name == L"stream" )
|
||||
MakeEzcStream(item.function);
|
||||
else
|
||||
CreateMsg(L"incorrect argument to [ezc] statement");
|
||||
if( item.function.name == L"out" )
|
||||
MakeEzcOut(item);
|
||||
|
||||
// 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)
|
||||
{
|
||||
item.type = Item::item_block;
|
||||
|
@ -827,6 +847,7 @@ std::wstring name;
|
|||
else if( name == L"def" ) ReadDirectiveDef(item);
|
||||
else if( name == L"filter" ) ReadDirectiveFilter(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"return" ) ReadDirectiveReturn(item);
|
||||
else if( name == L"#" ) ReadDirectiveComment(item);
|
||||
|
@ -990,7 +1011,8 @@ void PatternParser::CreateTree(Item & item)
|
|||
CreateTreeReadIf(*pitem);
|
||||
|
||||
if( pitem->type == Item::item_for ||
|
||||
pitem->type == Item::item_filter )
|
||||
pitem->type == Item::item_filter ||
|
||||
pitem->type == Item::item_ezc )
|
||||
CreateTreeReadFor(*pitem);
|
||||
|
||||
if( pitem->type == Item::item_include )
|
||||
|
|
|
@ -172,6 +172,7 @@ private:
|
|||
void ReadDirectiveDef(Item & item);
|
||||
void ReadDirectiveFilter(Item & item);
|
||||
void ReadDirectiveEzc(Item & item);
|
||||
void ReadDirectiveOut(Item & item);
|
||||
void ReadDirectiveBlock(Item & item);
|
||||
void ReadDirectiveReturn(Item & item);
|
||||
void ReadDirectiveNormal(const std::wstring & name, Item & item);
|
||||
|
|
Loading…
Reference in New Issue