renamed macro: EZC_HAS_SPECIAL_STREAM -> EZC_GENERATOR_HAS_PT_STREAM

added macro EZC_GENERATOR_HAS_WINIX_STREAM which is used by Generator::CopyStream(pt::WTextStream & src_stream, StreamType & dst_stream, bool should_escape)
if this macro is defined then Generator is able to escape output stream
This commit is contained in:
Tomasz Sowa 2021-06-20 16:54:55 +02:00
parent 9c4fe51790
commit 615bad7372
2 changed files with 124 additions and 86 deletions

View File

@ -50,6 +50,9 @@
#include "expressionparser.h" #include "expressionparser.h"
#include "models.h" #include "models.h"
#include "log/log.h" #include "log/log.h"
#include "utf8/utf8.h"
#ifdef EZC_HAS_MORM_LIBRARY #ifdef EZC_HAS_MORM_LIBRARY
#include "model.h" #include "model.h"
@ -288,6 +291,11 @@ private:
void ClearEzcFrameTab(); void ClearEzcFrameTab();
void ClearStream(StreamType & str); void ClearStream(StreamType & str);
void CopyStreamToString(StreamType & src_stream, std::wstring & dst_string);
void CopyStream(StreamType & src_stream, StreamType & dst_stream);
void CopyStream(pt::WTextStream & src_stream, StreamType & dst_stream, bool should_escape);
void RemoveStackFunData(Stack & sitem); void RemoveStackFunData(Stack & sitem);
bool ConvertToBool(const std::wstring & str); bool ConvertToBool(const std::wstring & str);
@ -357,7 +365,6 @@ private:
void TrimWhite(const wchar_t *& start, const wchar_t *& end); void TrimWhite(const wchar_t *& start, const wchar_t *& end);
void SkipWhite(const wchar_t *& str); void SkipWhite(const wchar_t *& str);
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 CopyStream(pt::TextStream src_stream, StreamType & dst_stream, bool should_escape);
bool ShouldEscapeValue(std::vector<Var> parameters); bool ShouldEscapeValue(std::vector<Var> parameters);
@ -379,7 +386,7 @@ private:
void MakeTextFor(Item & item); void MakeTextFor(Item & item);
void MakeItemText(Item & item); void MakeItemText(Item & item);
void MakeTextContainer(Item & item); void MakeTextContainer(Item & item);
void MakeTextNormal(Item & item); void MakeTextFunction(Item & item);
void MakeTextDefine(Item & item, Var & var); void MakeTextDefine(Item & item, Var & var);
void MakeTextDefine(Item & item); void MakeTextDefine(Item & item);
void MakeTextDefineIfNotSet(Item & item); void MakeTextDefineIfNotSet(Item & item);
@ -708,14 +715,91 @@ void Generator<StreamType>::ClearForStack()
template<class StreamType> template<class StreamType>
void Generator<StreamType>::ClearStream(StreamType & str) void Generator<StreamType>::ClearStream(StreamType & str)
{ {
#ifdef EZC_HAS_SPECIAL_STREAM #ifdef EZC_GENERATOR_HAS_PT_STREAM
str.Clear(); str.clear();
#else #else
str.str(L""); str.str(L"");
#endif #endif
} }
template<class StreamType>
void Generator<StreamType>::CopyStreamToString(StreamType & src_stream, std::wstring & dst_string)
{
if constexpr (sizeof(wchar_t) == sizeof(typename StreamType::char_type))
{
#ifdef EZC_GENERATOR_HAS_PT_STREAM
src_stream.to_str(dst_string);
#else
dst_string = src_stream.str();
#endif
}
else
{
#ifdef EZC_GENERATOR_HAS_PT_STREAM
src_stream.to_str(dst_string);
#else
std::string tmp = src_stream.str();
pt::utf8_to_wide(tmp, dst_string);
#endif
}
}
template<class StreamType>
void Generator<StreamType>::CopyStream(StreamType & src_stream, StreamType & dst_stream)
{
#ifdef EZC_GENERATOR_HAS_PT_STREAM
dst_stream << src_stream;
#else
dst_stream << src_stream.str();
#endif
}
template<class StreamType>
void Generator<StreamType>::CopyStream(pt::WTextStream & src_stream, StreamType & dst_stream, bool should_escape)
{
if constexpr(sizeof(char) == sizeof(typename StreamType::char_type))
{
// winix html stream is always wide (wchar_t)
// so if we are here then the dst_stream cannot be a Winix::HtmlTextStream
#ifndef EZC_GENERATOR_HAS_WINIX_STREAM
wide_stream_to_utf8(src_stream, dst_stream, false);
#endif
}
else
{
pt::WTextStream::iterator i = src_stream.begin();
while( i != src_stream.end() )
{
#ifdef EZC_GENERATOR_HAS_WINIX_STREAM
// IMPROVEME we need a better api from winix htmltextstream
if( should_escape )
{
dst_stream << *i;
}
else
{
dst_stream.write(&(*i), 1);
}
#else
dst_stream.write(&(*i), 1);
#endif
++i;
}
}
}
template<class StreamType> template<class StreamType>
void Generator<StreamType>::RemoveStackFunData(Stack & s) void Generator<StreamType>::RemoveStackFunData(Stack & s)
{ {
@ -1008,6 +1092,13 @@ bool Generator<StreamType>::Find(Item::Function & item_fun, FindHelper & find_he
#ifdef EZC_HAS_MORM_LIBRARY #ifdef EZC_HAS_MORM_LIBRARY
if( FindInModels(find_helper) ) if( FindInModels(find_helper) )
return true; return true;
if( !item_fun.fields.empty() )
{
CreateMsg(L"unknown model", find_helper.fun_name->c_str());
return false;
}
#endif #endif
if( CheckBlockArgument(item_fun.arg, find_helper) ) if( CheckBlockArgument(item_fun.arg, find_helper) )
@ -1092,34 +1183,6 @@ void Generator<StreamType>::CallObject(BaseObj<StreamType> & base_obj, int metho
template<class StreamType>
void Generator<StreamType>::CopyStream(pt::TextStream src_stream, StreamType & dst_stream, bool should_escape)
{
pt::TextStream::iterator i = src_stream.begin();
while( i != src_stream.end() )
{
if( should_escape )
{
dst_stream << *i;
}
else
{
if constexpr(sizeof(pt::TextStream::char_type) == sizeof(typename StreamType::char_type))
{
dst_stream.write(&(*i), 1);
}
else
{
wchar_t buf = static_cast<unsigned char>(*i);
dst_stream.write(&buf, 1);
}
}
++i;
}
}
template<class StreamType> template<class StreamType>
@ -1148,11 +1211,11 @@ bool Generator<StreamType>::CallModel(morm::Model & model, const std::wstring &
{ {
/* /*
* if 'field' is a POD type then 'str' will be used in get_raw_value() * if 'field' is a POD type then 'str' will be used in get_raw_value()
* if 'field' is a getter method with pt::TextStream then 'str' will be used too * if 'field' is a getter method with pt::Stream then 'str' will be used too
* if 'field' is a getter method which takes FunInfo<> then out_stream will be used and 'str' will be empty * if 'field' is a getter method which takes FunInfo<> then out_stream will be used and 'str' will be empty
* *
*/ */
pt::TextStream str; pt::WTextStream str;
bool found = false; bool found = false;
if( parameters.empty() ) if( parameters.empty() )
@ -1168,7 +1231,7 @@ bool Generator<StreamType>::CallModel(morm::Model & model, const std::wstring &
last_res = info.res; last_res = info.res;
} }
if( found ) if( found && !str.empty())
{ {
bool should_escape = ShouldEscapeValue(parameters); bool should_escape = ShouldEscapeValue(parameters);
CopyStream(str, out_stream, should_escape); CopyStream(str, out_stream, should_escape);
@ -1320,13 +1383,7 @@ bool Generator<StreamType>::CallBlock(Item & item_block,
MakeText(item_block); MakeText(item_block);
#ifdef EZC_HAS_SPECIAL_STREAM CopyStream(*output_stream, out_stream);
const std::wstring & str = output_stream->Str();
#else
const std::wstring & str = output_stream->str();
#endif
out_stream.write(str.c_str(), str.size());
// last_res is set by [return ...] statement or other last evaluated function // last_res is set by [return ...] statement or other last evaluated function
ClearStream(*output_stream); ClearStream(*output_stream);
@ -1392,12 +1449,7 @@ std::vector<Var> parameters;
StreamType local_temp_stream; StreamType local_temp_stream;
Call(fun_child, nullptr, local_temp_stream, true, empty_stream); Call(fun_child, nullptr, local_temp_stream, true, empty_stream);
#ifdef EZC_HAS_SPECIAL_STREAM CopyStreamToString(local_temp_stream, parameters[i].str);
parameters[i].str = local_temp_stream.Str();
#else
parameters[i].str = local_temp_stream.str();
#endif
parameters[i].res = last_res; parameters[i].res = last_res;
} }
else else
@ -1621,42 +1673,33 @@ void Generator<StreamType>::CopyTmpStreamToOutputStreams(Item::Function & fun, S
{ {
if( output_frames_streams ) if( output_frames_streams )
{ {
#ifdef EZC_HAS_SPECIAL_STREAM CopyStream(ezc_out_tmp_stream, previous_stream);
const std::wstring & str = ezc_out_tmp_stream.Str();
#else
const std::wstring & str = ezc_out_tmp_stream.str();
#endif
if( !str.empty() ) for(size_t s=0 ; s < fun.parameters.size() ; ++s)
{ {
previous_stream.write(str.c_str(), str.size()); std::wstring & name = fun.parameters[s]->name;
auto imap = output_frames_streams->streams_map.find(name);
for(size_t s=0 ; s < fun.parameters.size() ; ++s) if( imap == output_frames_streams->streams_map.end() )
{ {
std::wstring & name = fun.parameters[s]->name; if( output_frames_streams->streams_map.size() < output_frames_streams->streams_tab.size() )
auto imap = output_frames_streams->streams_map.find(name);
if( imap == output_frames_streams->streams_map.end() )
{ {
if( output_frames_streams->streams_map.size() < output_frames_streams->streams_tab.size() ) /* a new stream from the pool (output_stream_tab) is taken */
{ StreamType * stream = output_frames_streams->streams_tab[ output_frames_streams->streams_map.size() ];
/* a new stream from the pool (output_stream_tab) is taken */ output_frames_streams->streams_map.insert(std::make_pair(name, stream));
StreamType * stream = output_frames_streams->streams_tab[ output_frames_streams->streams_map.size() ]; ClearStream(*stream);
output_frames_streams->streams_map.insert(std::make_pair(name, stream)); CopyStream(ezc_out_tmp_stream, *stream);
ClearStream(*stream);
stream->write(str.c_str(), str.size());
}
else
{
CreateMsg(L"limit of output streams in OutStreams<> has been reached");
}
} }
else else
{ {
StreamType * stream = imap->second; CreateMsg(L"limit of output streams in OutStreams<> has been reached");
stream->write(str.c_str(), str.size());
} }
} }
else
{
StreamType * stream = imap->second;
CopyStream(ezc_out_tmp_stream, *stream);
}
} }
} }
} }
@ -1669,11 +1712,11 @@ void Generator<StreamType>::CreateMsg(const wchar_t * type, const wchar_t * arg)
{ {
if( plog ) if( plog )
{ {
(*plog) << pt::Log::log2 << L"Ezc: runtime error: " << type; (*plog) << pt::Log::log2 << "Ezc: " << type;
if( arg ) if( arg )
{ {
(*plog) << arg; (*plog) << ' ' << arg;
} }
(*plog) << pt::Log::logend; (*plog) << pt::Log::logend;
@ -1804,7 +1847,7 @@ void Generator<StreamType>::MakeTextContainer(Item & item)
template<class StreamType> template<class StreamType>
void Generator<StreamType>::MakeTextNormal(Item & item) void Generator<StreamType>::MakeTextFunction(Item & item)
{ {
is_generating_normal = true; is_generating_normal = true;
@ -1928,12 +1971,7 @@ void Generator<StreamType>::MakeTextDefine(Item & item, Var & var)
// call function // call function
if( Call(fun, nullptr, stream_temp_define, true, empty_stream) ) if( Call(fun, nullptr, stream_temp_define, true, empty_stream) )
{ {
#ifdef EZC_HAS_SPECIAL_STREAM CopyStreamToString(stream_temp_define, var.str);
var.str += stream_temp_define.Str();
#else
var.str += stream_temp_define.str();
#endif
var.res = last_res; var.res = last_res;
} }
else else
@ -2222,7 +2260,7 @@ void Generator<StreamType>::MakeText(Item & item)
if ( item.type == Item::item_text ) MakeItemText(item); if ( item.type == Item::item_text ) MakeItemText(item);
else if( item.type == Item::item_container ) MakeTextContainer(item); else if( item.type == Item::item_container ) MakeTextContainer(item);
else if( item.type == Item::item_function ) MakeTextNormal(item); else if( item.type == Item::item_function ) MakeTextFunction(item);
else if( item.type == Item::item_if ) MakeTextIf(item); else if( item.type == Item::item_if ) MakeTextIf(item);
else if( item.type == Item::item_def ) MakeTextDefine(item); else if( item.type == Item::item_def ) MakeTextDefine(item);
else if( item.type == Item::item_def_if_not_set ) MakeTextDefineIfNotSet(item); else if( item.type == Item::item_def_if_not_set ) MakeTextDefineIfNotSet(item);

View File

@ -150,8 +150,8 @@ void OutStreams<StreamType>::ClearMap()
{ {
StreamType & str = *(i->second); StreamType & str = *(i->second);
#ifdef EZC_HAS_SPECIAL_STREAM #ifdef EZC_GENERATOR_HAS_PT_STREAM
str.Clear(); str.clear();
#else #else
str.str(L""); str.str(L"");
#endif #endif