diff --git a/src/generator.h b/src/generator.h index f77b1bb..f49f90c 100644 --- a/src/generator.h +++ b/src/generator.h @@ -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 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::ClearForStack() template void Generator::ClearStream(StreamType & str) { - #ifdef EZC_HAS_SPECIAL_STREAM - str.Clear(); + #ifdef EZC_GENERATOR_HAS_PT_STREAM + str.clear(); #else str.str(L""); #endif } + +template +void Generator::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 +void Generator::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 +void Generator::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 void Generator::RemoveStackFunData(Stack & s) { @@ -1008,6 +1092,13 @@ bool Generator::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::CallObject(BaseObj & base_obj, int metho -template -void Generator::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(*i); - dst_stream.write(&buf, 1); - } - } - - ++i; - } -} - template @@ -1148,11 +1211,11 @@ bool Generator::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::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::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 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::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::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::MakeTextContainer(Item & item) template -void Generator::MakeTextNormal(Item & item) +void Generator::MakeTextFunction(Item & item) { is_generating_normal = true; @@ -1928,12 +1971,7 @@ void Generator::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::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); diff --git a/src/outstreams.h b/src/outstreams.h index 5727044..df5840b 100644 --- a/src/outstreams.h +++ b/src/outstreams.h @@ -150,8 +150,8 @@ void OutStreams::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