diff --git a/src/Makefile.dep b/src/Makefile.dep index de37e9b..6b0e710 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -1,11 +1,11 @@ # DO NOT DELETE -blocks.o: blocks.h item.h funinfo.h functions.h ../../pikotools/utf8/utf8.h -blocks.o: cache.h -cache.o: cache.h item.h funinfo.h functions.h ../../pikotools/utf8/utf8.h -cache.o: blocks.h -item.o: item.h funinfo.h functions.h ../../pikotools/utf8/utf8.h -pattern.o: pattern.h item.h funinfo.h functions.h ../../pikotools/utf8/utf8.h -pattern.o: cache.h blocks.h -patternparser.o: patternparser.h blocks.h item.h funinfo.h functions.h -patternparser.o: ../../pikotools/utf8/utf8.h cache.h pattern.h +blocks.o: blocks.h item.h cache.h functions.h ../../pikotools/utf8/utf8.h +blocks.o: funinfo.h objects.h +cache.o: cache.h item.h functions.h ../../pikotools/utf8/utf8.h funinfo.h +cache.o: objects.h blocks.h +item.o: item.h +pattern.o: pattern.h item.h cache.h functions.h ../../pikotools/utf8/utf8.h +pattern.o: funinfo.h objects.h blocks.h +patternparser.o: patternparser.h blocks.h item.h cache.h functions.h +patternparser.o: ../../pikotools/utf8/utf8.h funinfo.h objects.h pattern.h diff --git a/src/blocks.h b/src/blocks.h index 9745c3a..4f925da 100644 --- a/src/blocks.h +++ b/src/blocks.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2014, Tomasz Sowa + * Copyright (c) 2014-2015, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -65,7 +65,9 @@ public: size_t Size() const; void Clear(); + template void CacheObjects(Objects & obj); template void CacheFunctions(Functions & fun); + void CacheBlocks(Blocks & blocks); void ClearCache(); @@ -76,6 +78,16 @@ private: }; +template +void Blocks::CacheObjects(Objects & obj) +{ + BlocksTable::iterator i = blocks_tab.begin(); + + for( ; i != blocks_tab.end() ; ++i) + Cache(obj, i->second); +} + + template void Blocks::CacheFunctions(Functions & fun) { diff --git a/src/cache.cpp b/src/cache.cpp index c539588..a6f1d69 100644 --- a/src/cache.cpp +++ b/src/cache.cpp @@ -72,6 +72,12 @@ void Cache(Blocks & blocks, Item & item) + + + + + + } // namespace Ezc diff --git a/src/cache.h b/src/cache.h index 36e0b4a..b749337 100644 --- a/src/cache.h +++ b/src/cache.h @@ -41,6 +41,8 @@ #include "item.h" #include "functions.h" +#include "objects.h" + @@ -83,6 +85,38 @@ void Cache(Blocks & blocks, Item & item); + +template +void Cache(Objects & objects, Item::Function & function) +{ + function.base_obj = 0; + function.method_index = -1; + + if( !function.name.empty() && function.arg < 0 ) + { + typename Objects::Iterator i = objects.Find(function.name, function.method_index); + + if( i != objects.End() ) + function.base_obj = *i; + } + + for(size_t i=0 ; i < function.parameters.size() ; ++i) + Cache(objects, *function.parameters[i]); +} + + + +template +void Cache(Objects & objects, Item & item) +{ + Cache(objects, item.function); + + for(size_t i=0; i < item.item_tab.size() ; ++i) + Cache(objects, *item.item_tab[i]); +} + + + } // namespace Ezc diff --git a/src/functions.h b/src/functions.h index 15a3805..8889470 100644 --- a/src/functions.h +++ b/src/functions.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2007-2014, Tomasz Sowa + * Copyright (c) 2007-2015, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,6 +49,7 @@ namespace Ezc + // functions or variables template class Functions diff --git a/src/generator.h b/src/generator.h index b4c834e..5d36942 100644 --- a/src/generator.h +++ b/src/generator.h @@ -42,6 +42,7 @@ #include "blocks.h" #include "pattern.h" #include "functions.h" +#include "objects.h" #include #include #include @@ -69,6 +70,8 @@ public: void SetPattern(Pattern & pattern); void SetBlocks(Blocks & blocks); void SetFunctions(Functions & functions); + void SetObjects(Objects & objects); + void SetMax(size_t max_items_, size_t max_for_items_); @@ -155,6 +158,7 @@ private: Pattern * ppattern; Blocks * pblocks; Functions * pfunctions; + Objects * 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 @@ -242,19 +246,28 @@ private: template CharType ToLower(CharType c); - bool FindInCache(const Item::Function & item_fun, + + bool CheckBlockArgument(Item::Function & item_fun, std::wstring ** variable); + + bool FindInCache(Item::Function & item_fun, + BaseObj ** base_obj, + int * method_index, typename Functions::UserFunction ** function, - Item ** item_block, - std::wstring ** variable); + Item ** item_block); bool FindInFunctionsAndBlocks(const std::wstring & name, + BaseObj ** base_obj, + int * method_index, typename Functions::UserFunction ** function, Item ** item_block); bool FindInVariables(const std::wstring & name, std::wstring ** variable); - bool Find(const Item::Function & item_fun, + + bool Find(Item::Function & item_fun, + BaseObj ** base_obj, + int * method_index, typename Functions::UserFunction ** function, Item ** item_block, std::wstring ** variable); @@ -271,6 +284,17 @@ private: std::vector & parameters, StreamType & out_stream); + + void CallObject(BaseObj * base_obj, int method_index, FunInfo & info); + + + void CallObject(BaseObj * base_obj, + int method_index, + std::vector & parameters, + StreamType & out_stream, + const StreamType & in_stream); + + bool Call(Item::Function & item_fun, StreamType & out_stream, bool clear_out_stream, @@ -328,6 +352,7 @@ Generator::Generator() : empty_stream() ppattern = 0; pblocks = 0; pfunctions = 0; + pobjects = 0; max_items = 50000; max_for_items = 5000; @@ -364,6 +389,7 @@ Generator & Generator::operator=(const Generator::SetFunctions(Functions & functions) } +template +void Generator::SetObjects(Objects & objects) +{ + pobjects = &objects; +} + template void Generator::CanUseCache(bool can_use_cache) { @@ -766,34 +798,50 @@ void Generator::Generate(std::vector & o) } + template -bool Generator::FindInCache(const Item::Function & item_fun, - typename Functions::UserFunction ** function, - Item ** item_block, - std::wstring ** variable) +bool Generator::CheckBlockArgument(Item::Function & item_fun, std::wstring ** variable) { - if( item_fun.arg >= 0 ) + if( item_fun.arg < 0 ) + return false; + + empty_argument.clear(); + *variable = &empty_argument; + last_res = ConvertToBool(empty_argument); + + // it's a numeric function -- an argument to a block e.g.: [1] + if( block_stack_index > 0 ) { - empty_argument.clear(); - *variable = &empty_argument; + BlockStack & block_stack = block_stack_tab[block_stack_index-1]; - // it's a numeric function -- an argument to a block e.g.: [1] - if( block_stack_index > 0 ) + if( size_t(item_fun.arg) < block_stack.args.size() ) { - BlockStack & block_stack = block_stack_tab[block_stack_index-1]; - - if( size_t(item_fun.arg) < block_stack.args.size() ) - { - *variable = &block_stack.args[item_fun.arg].str; - last_res = block_stack.args[item_fun.arg].res; - } + *variable = &block_stack.args[item_fun.arg].str; + last_res = block_stack.args[item_fun.arg].res; } - - return true; } + return true; +} + + + +template +bool Generator::FindInCache(Item::Function & item_fun, + BaseObj ** base_obj, + int * method_index, + typename Functions::UserFunction ** function, + Item ** item_block) +{ if( can_find_in_cache ) { + if( item_fun.base_obj ) + { + *base_obj = reinterpret_cast * >(item_fun.base_obj); + *method_index = item_fun.method_index; + return true; + } + if( item_fun.fun_cache ) { *function = reinterpret_cast::UserFunction*>(item_fun.fun_cache); @@ -814,9 +862,22 @@ return false; template bool Generator::FindInFunctionsAndBlocks(const std::wstring & name, + BaseObj ** base_obj, + int * method_index, typename Functions::UserFunction ** function, Item ** item_block) { + if( pobjects ) + { + typename Objects::Iterator i = pobjects->Find(name, *method_index); + + if( i != pobjects->End() ) + { + *base_obj = *i; + return true; + } + } + if( pfunctions ) { typename Functions::Iterator i = pfunctions->Find(name); @@ -863,19 +924,26 @@ return false; template -bool Generator::Find(const Item::Function & item_fun, +bool Generator::Find(Item::Function & item_fun, + BaseObj ** base_obj, + int * method_index, typename Functions::UserFunction ** function, Item ** item_block, std::wstring ** variable) { + *base_obj = 0; + *method_index = -1; *function = 0; *item_block = 0; *variable = 0; - if( FindInCache(item_fun, function, item_block, variable) ) + if( CheckBlockArgument(item_fun, variable) ) return true; - if( FindInFunctionsAndBlocks(item_fun.name, function, item_block) ) + if( FindInCache(item_fun, base_obj, method_index, function, item_block) ) + return true; + + if( FindInFunctionsAndBlocks(item_fun.name, base_obj, method_index, function, item_block) ) return true; if( FindInVariables(item_fun.name, variable) ) @@ -928,6 +996,51 @@ void Generator::CallFunction(typename Functions::UserFun + + + + +template +void Generator::CallObject(BaseObj * base_obj, int method_index, FunInfo & info) +{ + info.Clear(); + + info.is_for = is_generating_for; + info.is_if = is_generating_if; + info.is_normal = is_generating_normal; + info.is_filter = is_generating_filter; + info.iter = info.stack.iter; + info.stack_tab = &stack_tab[0];//stack_tab.data();///////////////////////////////////////////////////////// + info.stack_index = stack_index-1; + + base_obj->CallFun(method_index, info); + + last_res = info.res; +} + + + +template +void Generator::CallObject(BaseObj * base_obj, + int method_index, + std::vector & parameters, + StreamType & out_stream, + const StreamType & in_stream) +{ + if( parameters.empty() ) + { + FunInfo info(out_stream, parameters, empty, in_stream, stack_tab[stack_index-1]); + CallObject(base_obj, method_index, info); + } + else + { + FunInfo info(out_stream, parameters, parameters[0].str, in_stream, stack_tab[stack_index-1]); + CallObject(base_obj, method_index, info); + } +} + + + template bool Generator::CallBlock(Item & item_block, std::vector & parameters, @@ -975,6 +1088,8 @@ bool Generator::Call(Item::Function & item_fun, bool clear_out_stream, const StreamType & in_stream) { +BaseObj * base_obj; +int method_index; typename Functions::UserFunction * fun; Item * item_block; std::wstring * variable; @@ -983,7 +1098,7 @@ std::vector parameters; if( clear_out_stream ) ClearStream(out_stream); - if( !Find(item_fun, &fun, &item_block, &variable) ) + if( !Find(item_fun, &base_obj, &method_index, &fun, &item_block, &variable) ) return false; parameters.resize(item_fun.parameters.size()); @@ -1012,6 +1127,9 @@ std::vector parameters; } } + if( base_obj ) + CallObject(base_obj, method_index, parameters, out_stream, in_stream); + else if( fun ) CallFunction(fun, parameters, out_stream, in_stream); else @@ -1446,26 +1564,11 @@ void Generator::MakeTextDefine(Item & item) template void Generator::MakeTextFilter(Item & item) { - typename Functions::UserFunction * function; - Item * item_block; - std::wstring * variable; - - if( !Find(item.function, &function, &item_block, &variable) ) - return; - - // IMPROVE ME - // what about blocks and variables? - // may when there is a block we can get the whole content from filter - // and put it as the first argument to the block? - if( !function ) - return; - if( filter_index >= filter_tab.size() ) { CreateMsg(L"Generator exceeded allowed number of filters"); return; } - StreamType * old_stream = output_stream; output_stream = filter_tab[filter_index]; diff --git a/src/item.cpp b/src/item.cpp index 234fbe7..36299cb 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -167,6 +167,8 @@ Item::~Item() void Item::ClearCache(Item::Function & function) { + function.base_obj = 0; + function.method_index = -1; function.fun_cache = 0; function.item_block = 0; diff --git a/src/item.h b/src/item.h index 69627b5..7570880 100644 --- a/src/item.h +++ b/src/item.h @@ -41,8 +41,7 @@ #include #include -#include "funinfo.h" -#include "functions.h" + namespace Ezc @@ -67,16 +66,20 @@ struct Item std::vector parameters; // if is_function is true then it is a function and can have 'parameters' // if is_functino is empty then 'parameters' is empty too void * fun_cache; // only valid if is_function is true - Item * item_block; + Item * item_block; + void * base_obj; + int method_index; int arg; // used if name is numeric (if no then is equal -1) Function() { - is_function = false; - fun_cache = 0; - item_block = 0; - arg = -1; + is_function = false; + fun_cache = 0; + item_block = 0; + base_obj = 0; + method_index = -1; + arg = -1; } ~Function() @@ -95,6 +98,8 @@ struct Item name = f.name; fun_cache = f.fun_cache; item_block = f.item_block; + base_obj = f.base_obj; + method_index = f.method_index; arg = f.arg; for(size_t i=0 ; i item_tab; // childs + std::vector item_tab; // childs bool has_function; // the [return] statement can be without a function Function function; diff --git a/src/objects.h b/src/objects.h new file mode 100644 index 0000000..5ec14ee --- /dev/null +++ b/src/objects.h @@ -0,0 +1,306 @@ +/* + * This file is a part of EZC -- Easy templating in C++ library + * and is distributed under the BSD 3-Clause licence. + * Author: Tomasz Sowa + */ + +/* + * 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_objects +#define headerfile_ezc_objects + +#include +#include +#include "utf8/utf8.h" + + + + +namespace Ezc +{ + + +template +class BaseObj +{ +public: + + virtual ~BaseObj() {} + + + /* + * + */ + virtual std::wstring & GetObjectName() = 0; + + + /* + * + */ + virtual int FindFun(const std::wstring & fun_name) = 0; + + + /* + * + */ + virtual void CallFun(int fun_index, FunInfo &) = 0; + + + /* + * + */ + virtual void ClearFunctions() = 0; + + + /* + * + */ + virtual size_t FunctionsSize() = 0; + + + /* + * + */ + virtual void AddFunctions() {}; + + +}; + + + + + +#define EZC_DEFINE_OBJECT_METHODS(classname) \ + \ + \ +protected: \ + \ + struct EzcTemplateMethod \ + { \ + std::wstring fun_name; \ + void (classname::*fun)(Info &); \ + }; \ + \ +public: \ + \ + virtual std::wstring & GetObjectName() \ + { \ + return ezc_object_name; \ + } \ + \ + virtual void CallFun(int fun_index, Info & info) \ + { \ + if( fun_index >=0 && (size_t)fun_index < ezc_template_method_tab.size() ) \ + { \ + (this->*(ezc_template_method_tab[fun_index].fun))(info); \ + } \ + } \ + \ + virtual int FindFun(const std::wstring & fun_name) \ + { \ + for(size_t i=0 ; i ezc_template_method_tab; \ +std::wstring ezc_object_name; \ + \ +private: + + + + + + + + + + + +template +class Objects +{ +public: + + typedef std::vector * > ObjectsTable; + typedef typename ObjectsTable::iterator Iterator; + + void Insert(BaseObj * base_fun); + void Insert(BaseObj & base_fun); + + Iterator Begin(); + Iterator End(); + size_t Size() const; + void Clear(); + + Iterator Find(const std::wstring & key, int & method_index); + +private: + + ObjectsTable obj_tab; + +}; + + + +template +typename Objects::Iterator Objects::Find(const std::wstring & key, int & method_index) +{ + Iterator i = obj_tab.begin(); + method_index = -1; + + for( ; i != obj_tab.end() ; ++i) + { + int index = (*i)->FindFun(key); + + if( index != -1 ) + { + method_index = index; + return i; + } + } + + return obj_tab.end(); +} + + + + +template +void Objects::Insert(BaseObj * base_fun) +{ + obj_tab.push_back(base_fun); +} + + +template +void Objects::Insert(BaseObj & base_fun) +{ + obj_tab.push_back(&base_fun); +} + + + +template +typename Objects::Iterator Objects::Begin() +{ + return obj_tab.begin(); +} + + +template +typename Objects::Iterator Objects::End() +{ + return obj_tab.end(); +} + + +template +size_t Objects::Size() const +{ + return obj_tab.size(); +} + + +template +void Objects::Clear() +{ + return obj_tab.clear(); +} + + + + +} // namespace Ezc + + +#endif diff --git a/src/pattern.h b/src/pattern.h index 8cc8d73..28235d7 100644 --- a/src/pattern.h +++ b/src/pattern.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2007-2014, Tomasz Sowa + * Copyright (c) 2007-2015, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,6 +44,7 @@ #include "cache.h" #include "blocks.h" #include "functions.h" +#include "objects.h" namespace Ezc @@ -60,6 +61,7 @@ public: template void CacheFunctions(Functions & fun); void CacheBlocks(Blocks & blocks); + template void CacheObjects(Objects & obj); void ClearCache(); @@ -77,6 +79,11 @@ void Pattern::CacheFunctions(Functions & fun) } +template +void Pattern::CacheObjects(Objects & obj) +{ + Cache(obj, item_root); +}