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 "models.h"
#include "log/log.h"
#include "utf8/utf8.h"
#ifdef EZC_HAS_MORM_LIBRARY
#include "model.h"
@ -288,6 +291,11 @@ private:
void ClearEzcFrameTab();
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);
bool ConvertToBool(const std::wstring & str);
@ -357,7 +365,6 @@ private:
void TrimWhite(const wchar_t *& start, const wchar_t *& end);
void SkipWhite(const wchar_t *& str);
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);
@ -379,7 +386,7 @@ private:
void MakeTextFor(Item & item);
void MakeItemText(Item & item);
void MakeTextContainer(Item & item);
void MakeTextNormal(Item & item);
void MakeTextFunction(Item & item);
void MakeTextDefine(Item & item, Var & var);
void MakeTextDefine(Item & item);
void MakeTextDefineIfNotSet(Item & item);
@ -708,14 +715,91 @@ void Generator<StreamType>::ClearForStack()
template<class StreamType>
void Generator<StreamType>::ClearStream(StreamType & str)
{
#ifdef EZC_HAS_SPECIAL_STREAM
str.Clear();
#ifdef EZC_GENERATOR_HAS_PT_STREAM
str.clear();
#else
str.str(L"");
#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>
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
if( FindInModels(find_helper) )
return true;
if( !item_fun.fields.empty() )
{
CreateMsg(L"unknown model", find_helper.fun_name->c_str());
return false;
}
#endif
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>
@ -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 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
*
*/
pt::TextStream str;
pt::WTextStream str;
bool found = false;
if( parameters.empty() )
@ -1168,7 +1231,7 @@ bool Generator<StreamType>::CallModel(morm::Model & model, const std::wstring &
last_res = info.res;
}
if( found )
if( found && !str.empty())
{
bool should_escape = ShouldEscapeValue(parameters);
CopyStream(str, out_stream, should_escape);
@ -1320,13 +1383,7 @@ bool Generator<StreamType>::CallBlock(Item & item_block,
MakeText(item_block);
#ifdef EZC_HAS_SPECIAL_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());
CopyStream(*output_stream, out_stream);
// last_res is set by [return ...] statement or other last evaluated function
ClearStream(*output_stream);
@ -1392,12 +1449,7 @@ std::vector<Var> parameters;
StreamType local_temp_stream;
Call(fun_child, nullptr, local_temp_stream, true, empty_stream);
#ifdef EZC_HAS_SPECIAL_STREAM
parameters[i].str = local_temp_stream.Str();
#else
parameters[i].str = local_temp_stream.str();
#endif
CopyStreamToString(local_temp_stream, parameters[i].str);
parameters[i].res = last_res;
}
else
@ -1621,42 +1673,33 @@ void Generator<StreamType>::CopyTmpStreamToOutputStreams(Item::Function & fun, S
{
if( output_frames_streams )
{
#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
CopyStream(ezc_out_tmp_stream, previous_stream);
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;
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() )
{
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() ];
output_frames_streams->streams_map.insert(std::make_pair(name, stream));
ClearStream(*stream);
stream->write(str.c_str(), str.size());
}
else
{
CreateMsg(L"limit of output streams in OutStreams<> has been reached");
}
/* a new stream from the pool (output_stream_tab) is taken */
StreamType * stream = output_frames_streams->streams_tab[ output_frames_streams->streams_map.size() ];
output_frames_streams->streams_map.insert(std::make_pair(name, stream));
ClearStream(*stream);
CopyStream(ezc_out_tmp_stream, *stream);
}
else
{
StreamType * stream = imap->second;
stream->write(str.c_str(), str.size());
CreateMsg(L"limit of output streams in OutStreams<> has been reached");
}
}
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 )
{
(*plog) << pt::Log::log2 << L"Ezc: runtime error: " << type;
(*plog) << pt::Log::log2 << "Ezc: " << type;
if( arg )
{
(*plog) << arg;
(*plog) << ' ' << arg;
}
(*plog) << pt::Log::logend;
@ -1804,7 +1847,7 @@ void Generator<StreamType>::MakeTextContainer(Item & item)
template<class StreamType>
void Generator<StreamType>::MakeTextNormal(Item & item)
void Generator<StreamType>::MakeTextFunction(Item & item)
{
is_generating_normal = true;
@ -1928,12 +1971,7 @@ void Generator<StreamType>::MakeTextDefine(Item & item, Var & var)
// call function
if( Call(fun, nullptr, stream_temp_define, true, empty_stream) )
{
#ifdef EZC_HAS_SPECIAL_STREAM
var.str += stream_temp_define.Str();
#else
var.str += stream_temp_define.str();
#endif
CopyStreamToString(stream_temp_define, var.str);
var.res = last_res;
}
else
@ -2222,7 +2260,7 @@ void Generator<StreamType>::MakeText(Item & item)
if ( item.type == Item::item_text ) MakeItemText(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_def ) MakeTextDefine(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);
#ifdef EZC_HAS_SPECIAL_STREAM
str.Clear();
#ifdef EZC_GENERATOR_HAS_PT_STREAM
str.clear();
#else
str.str(L"");
#endif