diff --git a/src/Makefile.dep b/src/Makefile.dep index 915b961..8daf181 100755 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -1,8 +1,9 @@ # DO NOT DELETE -item.o: item.h funinfo.h -pattern.o: pattern.h item.h funinfo.h functions.h stringconv.h -pattern.o: ../../pikotools/utf8/utf8.h -patternparser.o: patternparser.h pattern.h item.h funinfo.h functions.h -patternparser.o: stringconv.h ../../pikotools/utf8/utf8.h +blocks.o: blocks.h item.h funinfo.h functions.h ../../pikotools/utf8/utf8.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 +patternparser.o: patternparser.h blocks.h item.h funinfo.h functions.h +patternparser.o: ../../pikotools/utf8/utf8.h pattern.h stringconv.o: stringconv.h +vars.o: vars.h diff --git a/src/Makefile.o.dep b/src/Makefile.o.dep index 2cbee2f..fd2d822 100755 --- a/src/Makefile.o.dep +++ b/src/Makefile.o.dep @@ -1 +1 @@ -o = item.o pattern.o patternparser.o stringconv.o +o = blocks.o item.o pattern.o patternparser.o stringconv.o vars.o diff --git a/src/blocks.cpp b/src/blocks.cpp new file mode 100644 index 0000000..26ffe29 --- /dev/null +++ b/src/blocks.cpp @@ -0,0 +1,38 @@ +#include "blocks.h" + + +namespace Ezc +{ + + +void Blocks::Insert(const std::wstring & name, const Item & item) +{ + blocks_tab[name] = item; +} + + +Blocks::Iterator Blocks::Find(const std::wstring & name) +{ + return blocks_tab.find(name); +} + + +Blocks::Iterator Blocks::Begin() +{ + return blocks_tab.begin(); +} + + +Blocks::Iterator Blocks::End() +{ + return blocks_tab.end(); +} + + +size_t Blocks::Size() +{ + return blocks_tab.size(); +} + + +} // namespace diff --git a/src/blocks.h b/src/blocks.h new file mode 100644 index 0000000..ffe58bb --- /dev/null +++ b/src/blocks.h @@ -0,0 +1,74 @@ +/* + * This file is a part of EZC -- Easy templating in C++ + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2014, 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_blocks +#define headerfile_ezc_blocks + +#include +#include +#include "item.h" + + +namespace Ezc +{ + + + +class Blocks +{ +public: + + typedef std::map BlocksTable; + typedef BlocksTable::iterator Iterator; + + void Insert(const std::wstring & name, const Item & item); + + Iterator Find(const std::wstring & name); + + Iterator Begin(); + Iterator End(); + size_t Size(); + +private: + + BlocksTable blocks_tab; + +}; + +} // namespace + +#endif diff --git a/src/functions.h b/src/functions.h index ab0086b..e639d4a 100755 --- a/src/functions.h +++ b/src/functions.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2007-2012, Tomasz Sowa + * Copyright (c) 2007-2014, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,8 +39,9 @@ #define headerfile_ezc_functions #include +#include "utf8/utf8.h" #include "funinfo.h" -#include "stringconv.h" + namespace Ezc @@ -55,95 +56,43 @@ class Functions public: typedef void (*UserFunction)(FunInfo &); - enum Type { function, variable }; - - struct Function - { - Function(); - - Type type; - UserFunction user_function; // used when type is 'function' - std::wstring variable; // used when type is 'variable' - }; - - typedef std::map FunctionsTable; + typedef std::map FunctionsTable; typedef typename FunctionsTable::iterator Iterator; - - void Insert(const char * key, UserFunction ufunction); // inserting a function - void Insert(const char * key, const char * var); // inserting a variable - void Insert(const char * key, const std::string & var); // inserting a variable - void Insert(const std::string & key, UserFunction ufunction); // inserting a function - void Insert(const std::string & key, const char * var); // inserting a variable - void Insert(const std::string & key, const std::string & var); // inserting a variable + void Insert(const char * key, UserFunction ufunction); + void Insert(const std::string & key, UserFunction ufunction); + void Insert(const wchar_t * key, UserFunction ufunction); void Insert(const std::wstring & key, UserFunction ufunction); - void Insert(const std::wstring & key, const wchar_t * var); - void Insert(const std::wstring & key, const std::wstring & var); - bool Find(const std::string & key, Function ** fun); - bool Find(const std::wstring & key, Function ** fun); + typename Iterator Find(const std::wstring & key); Iterator Begin(); Iterator End(); - size_t Size() const; - void Clear(); + size_t Size() const; + void Clear(); + private: + FunctionsTable functions_tab; std::wstring temp_key; + }; -template -Functions::Function::Function() -{ - type = Functions::variable; - user_function = 0; -} - - template void Functions::Insert(const char * key, UserFunction ufunction) { - Function f; - f.type = function; - f.user_function = ufunction; - - AssignString(key, temp_key); - functions_tab[temp_key] = f; + PT::UTF8ToWide(key, temp_key); + functions_tab[temp_key] = ufunction; + temp_key.clear(); } -template -void Functions::Insert(const char * key, const char * var) -{ - Function f; - f.type = variable; - AssignString(var, f.variable); - - AssignString(key, temp_key); - functions_tab[temp_key] = f; -} - - -template -void Functions::Insert(const char * key, const std::string & var) -{ - Function f; - f.type = variable; - AssignString(var, f.variable); - - AssignString(key, temp_key); - functions_tab[temp_key] = f; -} - - - - template void Functions::Insert(const std::string & key, UserFunction ufunction) { @@ -152,54 +101,18 @@ void Functions::Insert(const std::string & key, UserFunction ufuncti template -void Functions::Insert(const std::string & key, const char * var) +void Functions::Insert(const wchar_t * key, UserFunction ufunction) { - Insert(key.c_str(), var); + temp_key = key; + functions_tab[temp_key] = ufunction; + temp_key.clear(); } -template -void Functions::Insert(const std::string & key, const std::string & var) -{ - Insert(key.c_str(), var); -} - - - - - - template void Functions::Insert(const std::wstring & key, UserFunction ufunction) { - Function f; - f.type = function; - f.user_function = ufunction; - - functions_tab[key] = f; -} - - - -template -void Functions::Insert(const std::wstring & key, const wchar_t * var) -{ - Function f; - f.type = variable; - f.variable = var; - - functions_tab[key] = f; -} - - -template -void Functions::Insert(const std::wstring & key, const std::wstring & var) -{ - Function f; - f.type = variable; - f.variable = var; - - functions_tab[key] = f; + functions_tab[key] = ufunction; } @@ -207,25 +120,12 @@ void Functions::Insert(const std::wstring & key, const std::wstring -template -bool Functions::Find(const std::string & key, Function ** fun) -{ - AssignString(key, temp_key); - return Find(temp_key, fun); -} template -bool Functions::Find(const std::wstring & key, Function ** fun) +typename Functions::Iterator Functions::Find(const std::wstring & key) { - typename FunctionsTable::iterator i = functions_tab.find( key ); - - if( i == functions_tab.end() ) - return false; - - *fun = &(i->second); - -return true; + return functions_tab.find(key); } diff --git a/src/funinfo.h b/src/funinfo.h index 2c54ef1..b33d876 100755 --- a/src/funinfo.h +++ b/src/funinfo.h @@ -90,6 +90,15 @@ struct Stack Clear(); } + ~Stack() + { + if( fun_data && remove ) + { + delete fun_data; + fun_data = 0; + } + } + void Clear() { iter = 0; @@ -107,17 +116,12 @@ struct FunInfo // output stream StreamType & out; - // the out stream is treated in case sensitive - // used only in [is...] statements - // default: true - bool case_sensitive; - // table of parameters // the table can be empty std::vector & params; // the first parameter - // you can always use it even if there is not any parameters (params is empty) + // you can always use it even if there are not any parameters (params is empty) // in such a way the reference points to an empty string const std::wstring & par; @@ -129,7 +133,7 @@ struct FunInfo bool is_for; // indicates that this function is from [if ...] statement - // is true for all kind of if's: if-one, if-any, if-no.... + // it is true for all kind of if's: if-one, if-any, if-no.... bool is_if; // indicates that this function is from [is ...] or [is-no ...] statements @@ -141,28 +145,26 @@ struct FunInfo // indicates that this function is from a filter statement [filter ...] bool is_filter; - // a pointer to a stack's item from generator's stack - // it is never null + // a stack's item from generator's stack // each function has a new stack item // on this stack you have iter (description below) and fun_data pointer // you can assign to it your own object derived from FunData - Stack * stack; + Stack & stack; - // the same as stack->iter (this is mainly for backward compatibility) + // the same as stack.iter (this is mainly for backward compatibility) // it indicates the number of a current iteration for the [for] statement (the first iteration is 0) // for other statements than [for] this is always zero size_t iter; // return value from a user's function (default false if not set directly by the function) - // for a variable it is set to true if the variable is not empty bool res; - // arguments: output_stream, table_of_parameters, the_first_parameter FunInfo(StreamType & o, std::vector & pars, const std::wstring & first_par, - const StreamType & i) : out(o), params(pars), par(first_par), in(i) + const StreamType & input_stream, + Stack & s) : out(o), params(pars), par(first_par), in(input_stream), stack(s) { Clear(); } @@ -176,9 +178,7 @@ struct FunInfo is_is = false; is_normal = false; is_filter = false; - stack = 0; iter = 0; - case_sensitive = true; } }; diff --git a/src/generator.h b/src/generator.h index 67a7b57..dfccfff 100755 --- a/src/generator.h +++ b/src/generator.h @@ -39,6 +39,8 @@ #ifndef headerfile_ezc_generator #define headerfile_ezc_generator +#include "vars.h" +#include "blocks.h" #include "pattern.h" #include "functions.h" #include @@ -65,6 +67,10 @@ public: Generator & operator=(const Generator & n); ~Generator(); + void SetPattern(Pattern & pattern); + void SetVars(Vars & vars); + void SetBlocks(Blocks & blocks); + void SetFunctions(Functions & functions); void SetMax(size_t max_items_, size_t max_for_items_); @@ -102,34 +108,52 @@ public: void SkipStream(int stream_index); // the main methods for generating - void Generate(StreamType & o, Pattern & p, Functions & f); - void Generate(std::vector & o, Pattern & p, Functions & f); - void Generate(std::vector & o, Pattern & p, Functions & f); - // this method is used only if the pattern has cached functions - void Generate(StreamType & o, Pattern & p); - void Generate(std::vector & o, Pattern & p); - void Generate(std::vector & o, Pattern & p); + void Generate(StreamType & o); + void Generate(std::vector & o); + void Generate(std::vector & o); private: + struct BlockStack + { + std::vector args; + StreamType * out_stream; + }; + + std::vector block_stack_tab; + size_t block_stack_index; + size_t block_stack_size; + // current output stream - // if we are printing only to one stream e.g. [put stream "3"] + // 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. [put stream "0" "2" "5"] + // 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. [put stream] without arguments - // in such a case we do not print anything + // 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) StreamType * output_stream; - Pattern * pattern; - Functions * functions; + + Pattern * ppattern; + Vars * pvars; + Blocks * pblocks; + Functions * pfunctions; // 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; + // local_temp_stream is used when there are nested function calls + // e.g.: [function1 [function2]] + // function2 will be redirected to local_temp_stream and the string + // will be copied to Item::function.par std::wstring object + StreamType local_temp_stream; + + + std::vector parameters; + // pointers to the output streams std::vector output_stream_tab; @@ -164,12 +188,12 @@ private: std::vector filter_tab; const StreamType empty_stream; + // used in [0] [1] [2] when there is no such argument defined + std::wstring empty_argument; + // temporary streams used in [if..] [is...] or [for...] // or if output_stream is null and an ezc function should be called - StreamType stream_temp1, stream_temp2; - - // whether last function has put its content in case_sensitive (set FunInfo::case_sensitive) - bool last_case_sensitive; + StreamType stream_temp1, stream_temp2, stream_temp_define; // last result from a user function (FunInfo::res) bool last_res; @@ -194,29 +218,56 @@ private: void ResizeFilterTab(); void ResizeStack(); + void ResizeBlockStack(); + void ClearFilterTab(); - void ClearForStack(bool resize_stack = true); + void ClearForStack(); void ClearStream(StreamType & str); void RemoveStackFunData(Stack & sitem); template CharType ToLower(CharType c); - template - bool StrCmpNc(CharType * str1, CharType * str2); + bool AreStreamsEqual(StreamType & str1, StreamType & str2); + const std::wstring & GetStringFromStream(StreamType & str); - bool AreStreamsEqual(StreamType & str1, StreamType & str2, bool case_sensitive); + bool FindInCache(const Item::Function & item_fun, + typename Functions::UserFunction ** function, + Item ** item_block, + std::wstring ** variable); + bool FindInFunctionsAndBlocks(const std::wstring & name, + typename Functions::UserFunction ** function, + Item ** item_block); + + bool FindInVariables(const std::wstring & name, + typename Functions::UserFunction ** function, + Item ** item_block, + std::wstring ** variable); - bool Find(const Item::Function & item_fun, typename Functions::Function ** function); - - void Call(typename Functions::Function * function, FunInfo & info); - void Call(typename Functions::Function * function, std::vector & params, - StreamType & out_stream, bool clear_out_stream, const StreamType & in_stream); + bool Find(const Item::Function & item_fun, + typename Functions::UserFunction ** function, + Item ** item_block, + std::wstring ** variable); - bool Call(Item::Function & item_fun, StreamType & out_stream, bool clear_out_stream); - bool Call(Item::Function & function); - + void CallFunction(typename Functions::UserFunction * function, + FunInfo & info); + + void CallFunction(typename Functions::UserFunction * function, + std::vector & params, + StreamType & out_stream, + const StreamType & in_stream); + + bool CallBlock(Item & item_block, + std::vector & params, + StreamType & out_stream); + + bool Call(Item::Function & item_fun, + StreamType & out_stream, + bool clear_out_stream, + const StreamType & in_stream); + + bool Call(Item::Function & item_fun); wchar_t CreateSpecialChar(wchar_t c); const wchar_t * PrintSpecialChar(const wchar_t * start, const wchar_t * end); @@ -245,7 +296,6 @@ private: void MakeTextIfanyno(Item & item); void MakeTextIfoneno(Item & item); void MakeTextIfindex(Item & item); - void MakeTextForLoop(Item & item, typename Functions::Function * function); void MakeTextFor(Item & item); void MakeItemText(Item & item); void MakeTextContainer(Item & item); @@ -260,7 +310,7 @@ private: void MakeEzcStream(Item::Function & fun); - void Generate(Pattern * p, Functions * f); + void Generate(); @@ -275,8 +325,10 @@ template Generator::Generator() : empty_stream() { output_stream = 0; - pattern = 0; - functions = 0; + ppattern = 0; + pvars = 0; + pblocks = 0; + pfunctions = 0; max_items = 50000; max_for_items = 5000; @@ -286,6 +338,7 @@ Generator::Generator() : empty_stream() skip_new_line = false; is_generator_working = false; stack_size = 300; + block_stack_size = 64; has_skip_stream_index = false; } @@ -307,8 +360,11 @@ Generator & Generator::operator=(const Generator & Generator::operator=(const Generator::~Generator() } +template +void Generator::SetPattern(Pattern & pattern) +{ + ppattern = &pattern; +} + + +template +void Generator::SetVars(Vars & vars) +{ + pvars = &vars; +} + + +template +void Generator::SetBlocks(Blocks & blocks) +{ + pblocks = &blocks; +} + + +template +void Generator::SetFunctions(Functions & functions) +{ + pfunctions = &functions; +} + + + template void Generator::ResizeFilterTab() { @@ -378,6 +465,30 @@ void Generator::ResizeStack() } +template +void Generator::ResizeBlockStack() +{ + if( block_stack_tab.size() != block_stack_size ) + { + if( block_stack_tab.size() < block_stack_size ) + { + size_t i = block_stack_tab.size(); + block_stack_tab.resize(block_stack_size); + + for( ; i void Generator::ClearFilterTab() { @@ -389,13 +500,10 @@ void Generator::ClearFilterTab() template -void Generator::ClearForStack(bool resize_stack) +void Generator::ClearForStack() { for(size_t i=0 ; i -template -bool Generator::StrCmpNc(CharType * str1, CharType * str2) -{ - for( ; ToLower(*str1) == ToLower(*str2) ; ++str1, ++str2) - if( *str1 == 0 ) - return true; -return false; +template +bool Generator::AreStreamsEqual(StreamType & str1, StreamType & str2) +{ + #ifdef EZC_HAS_SPECIAL_STREAM + return str1.Str() == str2.Str(); + #else + return str1.str() == str2.str(); + #endif } template -bool Generator::AreStreamsEqual(StreamType & str1, StreamType & str2, bool case_sensitive) +const std::wstring & Generator::GetStringFromStream(StreamType & stream) { - if( case_sensitive ) - { - #ifdef EZC_HAS_SPECIAL_STREAM - return str1.Str() == str2.Str(); - #else - return str1.str() == str2.str(); - #endif - } - else - { - #ifdef EZC_HAS_SPECIAL_STREAM - return StrCmpNc(str1.CStr(), str2.CStr()); - #else - return StrCmpNc(str1.str().c_str(), str2.str().c_str()); - #endif - } + #ifdef EZC_HAS_SPECIAL_STREAM + const std::wstring & str = stream.Str(); + #else + const std::wstring & str = stream.str(); + #endif + +return str; } @@ -529,7 +628,7 @@ void Generator::SetStackSize(size_t new_stack_size) template -void Generator::Generate(Pattern * p, Functions * f) +void Generator::Generate() { if( is_generator_working ) { @@ -550,27 +649,27 @@ void Generator::Generate(Pattern * p, Functions * f) } } - pattern = p; - functions = f; break_generating = false; current_item = 0; // in the case that there something has left on the stack // from previous call to Generate() // (an exception could have been thrown) - ClearForStack(false); + ClearForStack(); ResizeFilterTab(); ResizeStack(); + ResizeBlockStack(); filter_index = 0; stack_index = 0; + block_stack_index = 0; - if( pattern ) + if( ppattern ) { try { is_generator_working = true; - MakeText( pattern->item_root ); + MakeText( ppattern->item_root ); if( output_stream_index.size() > 1 ) WriteTmpStreamToStreams(); @@ -587,109 +686,170 @@ void Generator::Generate(Pattern * p, Functions * f) template -void Generator::Generate(StreamType & o, Pattern & p, Functions & f) +void Generator::Generate(StreamType & o) { output_stream_tab.resize(1); output_stream_tab[0] = &o; - Generate(&p, &f); + Generate(); } template -void Generator::Generate(std::vector & o, Pattern & p, Functions & f) +void Generator::Generate(std::vector & o) { output_stream_tab.resize(o.size()); for(size_t i=0 ; i -void Generator::Generate(std::vector & o, Pattern & p, Functions & f) +void Generator::Generate(std::vector & o) { output_stream_tab.resize(o.size()); for(size_t i=0 ; i -void Generator::Generate(StreamType & o, Pattern & p) -{ - output_stream_tab.resize(1); - output_stream_tab[0] = &o; - - Generate(&p, 0); -} - - - -template -void Generator::Generate(std::vector & o, Pattern & p) -{ - output_stream_tab.resize(o.size()); - - for(size_t i=0 ; i -void Generator::Generate(std::vector & o, Pattern & p) +bool Generator::FindInCache(const Item::Function & item_fun, + typename Functions::UserFunction ** function, + Item ** item_block, + std::wstring ** variable) { - output_stream_tab.resize(o.size()); - - for(size_t i=0 ; i -bool Generator::Find(const Item::Function & item_fun, typename Functions::Function ** function) -{ - if( !functions ) + if( item_fun.arg >=0 ) { - if( item_fun.fun_cache ) + empty_argument.clear(); + *variable = &empty_argument; + + // it's a numeric function -- an argument to a block e.g.: [1] + if( block_stack_index > 0 ) { - *function = reinterpret_cast::Function*>(item_fun.fun_cache); + 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]; + } + + return true; + } + + if( item_fun.fun_cache ) + { + *function = reinterpret_cast::UserFunction*>(item_fun.fun_cache); + return true; + } + + if( item_fun.item_block ) + { + *item_block = item_fun.item_block; + return true; + } + +return false; +} + + + +template +bool Generator::FindInFunctionsAndBlocks(const std::wstring & name, + typename Functions::UserFunction ** function, + Item ** item_block) +{ + if( pfunctions ) + { + Functions::Iterator i = pfunctions->Find(name); + + if( i != pfunctions->End() ) + { + *function = &i->second; return true; } - else + } + + if( pblocks ) + { + Blocks::Iterator i = pblocks->Find(name); + + if( i != pblocks->End() ) { - CreateUnknownMsg(item_fun.name); - return false; + *item_block = &i->second; + return true; } } - if( !functions->Find(item_fun.name, function) ) +return false; +} + + +template +bool Generator::FindInVariables(const std::wstring & name, + typename Functions::UserFunction ** function, + Item ** item_block, + std::wstring ** variable) +{ + if( pvars ) { - CreateUnknownMsg(item_fun.name); - return false; + Vars::Iterator i = pvars->Find(name); + + if( i != pvars->End() ) + { + Vars::Variable & var = i->second; + + if( var.type == Vars::variable_string ) + { + *variable = &var.val; + return true; + } + else + { + // this is an alias to a function or to a block + return FindInFunctionsAndBlocks(var.val, function, item_block); + } + } } - -return true; + +return false; +} + + +template +bool Generator::Find(const Item::Function & item_fun, + typename Functions::UserFunction ** function, + Item ** item_block, + std::wstring ** variable) +{ + *function = 0; + *item_block = 0; + *variable = 0; + + if( FindInCache(item_fun, function, item_block, variable) ) + return true; + + if( FindInFunctionsAndBlocks(item_fun.name, function, item_block) ) + return true; + + if( FindInVariables(item_fun.name, function, item_block, variable) ) + return true; + + CreateUnknownMsg(item_fun.name); + +return false; } template -void Generator::Call(typename Functions::Function * function, FunInfo & info) +void Generator::CallFunction(typename Functions::UserFunction * function, FunInfo & info) { info.Clear(); @@ -698,61 +858,130 @@ void Generator::Call(typename Functions::Function * func info.is_is = is_generating_is; info.is_normal = is_generating_normal; info.is_filter = is_generating_filter; + info.iter = info.stack.iter; - info.stack = &stack_tab[stack_index-1]; - info.iter = stack_tab[stack_index-1].iter; - - if( function->type == Functions::function ) - { - (function->user_function)(info); - } - else - { - info.out << function->variable; - info.res = !function->variable.empty(); - } + (*function)(info); last_res = info.res; - last_case_sensitive = info.case_sensitive; } template -void Generator::Call(typename Functions::Function * function, - std::vector & params, - StreamType & out_stream, - bool clear_out_stream, - const StreamType & in_stream) +void Generator::CallFunction(typename Functions::UserFunction * function, + std::vector & params, + StreamType & out_stream, + const StreamType & in_stream) { - if( clear_out_stream ) - ClearStream(out_stream); - if( params.empty() ) { - FunInfo info(out_stream, params, empty, in_stream); - Call(function, info); + FunInfo info(out_stream, params, empty, in_stream, stack_tab[stack_index-1]); + CallFunction(function, info); } else { - FunInfo info(out_stream, params, params[0], in_stream); - Call(function, info); + FunInfo info(out_stream, params, params[0], in_stream, stack_tab[stack_index-1]); + CallFunction(function, info); } } +template +bool Generator::CallBlock(Item & item_block, + std::vector & params, + StreamType & out_stream) +{ + if( block_stack_index >= block_stack_tab.size() ) + { + CreateMsg(L"Generator exceeded allowed number of blocks"); + return false; + } + + StreamType * old_stream = output_stream; + BlockStack & block_stack = block_stack_tab[block_stack_index]; + + block_stack.args.resize(params.size()); + + for(size_t i=0 ; i -bool Generator::Call(Item::Function & item_fun, StreamType & out_stream, bool clear_out_stream) +bool Generator::Call(Item::Function & item_fun, + StreamType & out_stream, + bool clear_out_stream, + const StreamType & in_stream) { -typename Functions::Function * fun; +typename Functions::UserFunction * fun; +Item * item_block; +std::wstring * variable; - if( !Find(item_fun, &fun) ) + if( clear_out_stream ) + ClearStream(out_stream); + + if( !Find(item_fun, &fun, &item_block, &variable) ) return false; - Call(fun, item_fun.params, out_stream, clear_out_stream, empty_stream); + for(size_t i=0 ; ipar; + } + } + + if( fun ) + { + CallFunction(fun, parameters, out_stream, in_stream); + } + else + if( item_block ) + { + return CallBlock(*item_block, parameters, out_stream); + } + else + if( variable ) + { + out_stream << *variable; + last_res = !variable->empty(); + } return true; } @@ -763,7 +992,7 @@ return true; template bool Generator::Call(Item::Function & item_fun) { - return Call(item_fun, stream_temp1, true); + return Call(item_fun, stream_temp1, true, empty_stream); } @@ -949,11 +1178,7 @@ return res; template void Generator::WriteTmpStreamToStreams() { - #ifdef EZC_HAS_SPECIAL_STREAM - const std::wstring & str = output_tmp_stream.Str(); - #else - const std::wstring & str = output_tmp_stream.str(); - #endif + const std::wstring & str = GetStringFromStream(output_tmp_stream); if( !str.empty() ) { @@ -977,7 +1202,7 @@ void Generator::CreateMsg(const wchar_t * type, const wchar_t * arg) { if( output_stream ) { - pattern->CreateMsg(temp_msg, type, arg); + ppattern->CreateMsg(temp_msg, type, arg); output_stream->write(temp_msg.c_str(), temp_msg.size()); } } @@ -1045,11 +1270,11 @@ void Generator::MakeTextNormal(Item & item) if( output_stream ) { - Call(item.functions[0], *output_stream, false); + Call(item.functions[0], *output_stream, false, empty_stream); } else { - Call(item.functions[0], stream_temp1, false); + Call(item.functions[0], stream_temp1, false, empty_stream); ClearStream(stream_temp1); } } @@ -1203,23 +1428,13 @@ void Generator::MakeTextIs(Item & item, bool equal) is_generating_is = true; - // if one of these two functions has set case_sensitive to false - // then we compare in case insensitive mode - bool case_sensitive = true; - - if( !Call(item.functions[0], stream_temp1, true) ) + if( !Call(item.functions[0], stream_temp1, true, empty_stream) ) return; - if( !last_case_sensitive ) - case_sensitive = false; - - if( !Call(item.functions[1], stream_temp2, true) ) + if( !Call(item.functions[1], stream_temp2, true, empty_stream) ) return; - if( !last_case_sensitive ) - case_sensitive = false; - - bool res = AreStreamsEqual(stream_temp1, stream_temp2, case_sensitive); + bool res = AreStreamsEqual(stream_temp1, stream_temp2); if( !equal ) res = !res; @@ -1321,8 +1536,11 @@ size_t for_index; template -void Generator::MakeTextForLoop(Item & item, typename Functions::Function * function) +void Generator::MakeTextFor(Item & item) { + if( item.functions.size() != 1 ) + return; + stack_tab[stack_index-1].is_for = true; for( ; !break_generating ; stack_tab[stack_index-1].iter += 1 ) @@ -1337,7 +1555,8 @@ void Generator::MakeTextForLoop(Item & item, typename Functions::MakeTextForLoop(Item & item, typename Functions -void Generator::MakeTextFor(Item & item) -{ - if( item.functions.size() != 1 ) - return; - - typename Functions::Function * function; - - if( !Find(item.functions[0], &function) ) - return; - - MakeTextForLoop(item, function); -} - - template void Generator::MakeTextDefine(Item & item) { - if( !functions ) + if( !pvars ) { - CreateMsg(L"[def] statement is not available when used without functions set"); + CreateMsg(L"[def] statement not available"); return; } - if( item.functions.size() == 1 ) + if( item.functions.size() == 1 && + item.functions[0].parameters.size() == 1 ) { - // inserting a new variable - if( item.functions[0].params.size() == 1 ) - functions->Insert(item.functions[0].name, item.functions[0].params[0]); + if( item.functions[0].parameters[0]->name.empty() ) + { + // it is [def name "string"] + pvars->Insert(item.functions[0].name, Vars::variable_string, item.functions[0].parameters[0]->par); + } + else + { + // it is [def name [function]] + if( Call(*item.functions[0].parameters[0], stream_temp_define, true, empty_stream) ) + { + const std::wstring & str = GetStringFromStream(stream_temp_define); + pvars->Insert(item.functions[0].name, Vars::variable_string, str); + } + } } else - if( item.functions.size() == 2 ) + if( item.functions.size() == 2 && + item.functions[0].parameters.empty() && + item.functions[1].parameters.empty() ) { - typename Functions::Function * function; + typename Functions::UserFunction * function; + Item * item_block; + std::wstring * variable; - if( Find(item.functions[1], &function) ) + if( Find(item.functions[1], &function, &item_block, &variable) ) { - if( function->type == Functions::function ) + if( variable ) { - // inserting a new function - functions->Insert(item.functions[0].name, function->user_function); + Vars::Iterator i = pvars->Find(*variable); + + if( i != pvars->End() ) + { + Vars::Variable & var = i->second; + pvars->Insert(*variable, var.type, var.val); + } } else { - // inserting a new variable (the value is copied) - functions->Insert(item.functions[0].name, function->variable); + pvars->Insert(item.functions[0].name, Vars::variable_alias, item.functions[1].name); } } + else + { + CreateMsg(L"[def] unknown function/block/variable", item.functions[1].name.c_str()); + } } } @@ -1409,9 +1637,18 @@ void Generator::MakeTextFilter(Item & item) if( item.functions.size() != 1 ) return; - typename Functions::Function * function; + typename Functions::UserFunction * function; + Item * item_block; + std::wstring * variable; - if( !Find(item.functions[0], &function) ) + if( !Find(item.functions[0], &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() ) @@ -1434,11 +1671,13 @@ void Generator::MakeTextFilter(Item & item) if( old_stream ) { - Call(function, item.functions[0].params, *old_stream, false, *output_stream); + //Call(function, item.functions[0].params, *old_stream, false, *output_stream); + Call(item.functions[0], *old_stream, false, *output_stream); } else { - Call(function, item.functions[0].params, stream_temp1, true, *output_stream); + //Call(function, item.functions[0].params, stream_temp1, true, *output_stream); + Call(item.functions[0], stream_temp1, true, *output_stream); ClearStream(stream_temp1); } @@ -1457,9 +1696,9 @@ void Generator::MakeEzcStream(Item::Function & fun) output_stream_index.clear(); - for(size_t i=0 ; ipar.c_str()); // !! CHECK ME or ->name ? if( index < output_stream_tab.size() ) { @@ -1505,6 +1744,7 @@ void Generator::MakeTextEzc(Item & item) + template bool Generator::LimitAchieved() { diff --git a/src/item.cpp b/src/item.cpp index b748026..89a8d57 100755 --- a/src/item.cpp +++ b/src/item.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2007-2011, Tomasz Sowa + * Copyright (c) 2007-2014, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -161,5 +161,17 @@ Item::~Item() +void Item::ClearCache() +{ + for(size_t f = 0; f < functions.size() ; ++f) + functions[f].fun_cache = 0; + + for(size_t i = 0; i < item_tab.size() ; ++i) + item_tab[i]->ClearCache(); +} + + + + } // namespace Ezc diff --git a/src/item.h b/src/item.h index 2f2548d..e5994dd 100755 --- a/src/item.h +++ b/src/item.h @@ -42,6 +42,7 @@ #include #include #include "funinfo.h" +#include "functions.h" namespace Ezc @@ -56,25 +57,79 @@ struct Item item_none, item_container, item_text, item_normal, item_is, item_isno, item_if, item_ifno, item_ifany, item_ifone, item_ifanyno, item_ifoneno, item_ifindex, item_for, item_else, item_end, item_err, item_include, item_comment, item_def, item_filter, - item_ezc + item_ezc, item_block }; + struct Function { - std::wstring name; // function name - std::vector params; // function parameters - void * fun_cache; + std::wstring name; // function name (can be empty, means there is no any function -- only a text parameter) + std::wstring par; // parameter + std::vector parameters; + void * fun_cache; // only valid if name is not empty + Item * item_block; + int arg; // used if name is numeric (if no then is equal -1) + Function() { - fun_cache = 0; + fun_cache = 0; + item_block = 0; + arg = -1; } + + ~Function() + { + Clear(); + } + + Function(const Function & f) + { + operator=(f); + } + + Function & operator=(const Function & f) + { + name = f.name; + par = f.par; + fun_cache = f.fun_cache; + item_block = f.item_block; + arg = f.arg; + + for(size_t i=0 ; i item_tab; // childs + std::vector item_tab; // childs std::vector functions; Item(); @@ -89,9 +144,45 @@ struct Item Type LastItemType(); void DeleteLastItem(); void Clear(); + + template + void CacheFunctions(Functions & fun); + + void ClearCache(); + }; +template +void Item::CacheFunctions(Functions & fun) +{ + // one exception (if_index is putting its argument on the functions stack) + if( type != Item::item_ifindex ) + { + for(size_t f=0; f < functions.size() ; ++f) + { + Functions::Iterator i = fun.Find(functions[f].name); + + if( i != fun.End() ) + { + functions[f].fun_cache = i->second; + } + else + { + functions[f].fun_cache = 0; +// teraz chyba nie trzeba tego logowac +// bo mamy zmienne i identyfikator moze byc znaleziony w runtime +// #ifdef EZC_USE_WINIX_LOGGER +// Winix::log << Winix::log1 << "Ezc: unknown function: " << item.functions[f].name << Winix::logend; +// #endif + } + } + } + + for(size_t i=0; i < item_tab.size() ; ++i) + item_tab[i]->CacheFunctions(fun); +} + } // namespace Ezc diff --git a/src/pattern.cpp b/src/pattern.cpp index da7114e..a9178f5 100755 --- a/src/pattern.cpp +++ b/src/pattern.cpp @@ -60,22 +60,6 @@ void Pattern::Clear() -void Pattern::ClearCache() -{ - ClearCache(item_root); -} - - - -void Pattern::ClearCache(Item & item) -{ - for(size_t f = 0; f < item.functions.size() ; ++f) - item.functions[f].fun_cache = 0; - - for(size_t i = 0; i < item.item_tab.size() ; ++i) - ClearCache(*item.item_tab[i]); -} - @@ -132,6 +116,8 @@ void Pattern::CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t + + } // namespace Ezc diff --git a/src/pattern.h b/src/pattern.h index 4f0d8c9..db99323 100755 --- a/src/pattern.h +++ b/src/pattern.h @@ -80,37 +80,7 @@ private: std::wstring commentary_start, commentary_stop; - template - void CacheFunctions(Item & item, Functions & fun) - { - typename Functions::Function * ezc_fun; - // one exception (if_index is putting its argument on the functions stack) - if( item.type != Item::item_ifindex ) - { - for(size_t f=0; f < item.functions.size() ; ++f) - { - if( fun.Find(item.functions[f].name, &ezc_fun) ) - { - item.functions[f].fun_cache = ezc_fun; - } - else - { - item.functions[f].fun_cache = 0; - - #ifdef EZC_USE_WINIX_LOGGER - Winix::log << Winix::log1 << "Ezc: unknown function: " << item.functions[f].name << Winix::logend; - #endif - } - } - } - - for(size_t i=0; i < item.item_tab.size() ; ++i) - CacheFunctions(*item.item_tab[i], fun); - } - - - void ClearCache(Item & item); }; // class Pattern diff --git a/src/patternparser.cpp b/src/patternparser.cpp index cf22e10..4a99e5f 100755 --- a/src/patternparser.cpp +++ b/src/patternparser.cpp @@ -48,10 +48,9 @@ namespace Ezc PatternParser::PatternParser() { allow_include = true; - input_as_utf8 = true; + pblocks = 0; + include_level_max = 100; delete_white_text_items = false; - - include_level_max = 100; } @@ -116,6 +115,12 @@ void PatternParser::Directory(const std::wstring & dir, const std::wstring & dir +void PatternParser::SetBlocks(Blocks & blocks) +{ + pblocks = &blocks; +} + + void PatternParser::ParseFile(const std::string & file_name, Pattern & pattern) { ParseFile(file_name.c_str(), pattern); @@ -156,11 +161,7 @@ void PatternParser::ParseFile(const wchar_t * file_name, Pattern & pattern) void PatternParser::ParseString(const char * str, Pattern & pattern) { - if( input_as_utf8 ) - PT::UTF8ToWide(str, string_content); - else - AssignString(str, string_content); - + PT::UTF8ToWide(str, string_content); ParseString(string_content.c_str(), pattern); string_content.clear(); } @@ -218,16 +219,6 @@ void PatternParser::SetIncludeMax(int include_max) -void PatternParser::UTF8(bool utf8) -{ - input_as_utf8 = utf8; -} - - - - - - @@ -343,38 +334,13 @@ return true; - void PatternParser::ReadFile(std::ifstream & file, std::wstring & result) { - if( input_as_utf8 ) - { - PT::UTF8ToWide(file, result); - } - else - { - ReadFileContent(file, result); - } + PT::UTF8ToWide(file, result); } - -void PatternParser::ReadFileContent(std::ifstream & file, std::wstring & result) -{ - while( true ) - { - int c = file.get(); - - if( !file ) - break; - - result += static_cast(c); - } -} - - - - int PatternParser::ReadCharInText() { if( *itext==0 || *itext=='[' ) @@ -519,14 +485,38 @@ return true; bool PatternParser::ReadParams(Item::Function & function) { - function.params.clear(); + while( true ) + { + SkipWhite(); - while( ReadString(temp_param) ) - function.params.push_back(temp_param); + if( *itext == '[' ) + { + ++itext; // skipping '[' + ReadFunction(function.AddNewParam()); - temp_param.clear(); + SkipWhite(); + if( *itext == ']' ) + ++itext; + } + else + if( *itext == '\"' ) + { + if( ReadString(temp_param) ) + { + Item::Function & fun = function.AddNewParam(); + fun.par = temp_param; + // fun.name is empty so it is treated as a text parameter + } -return !function.params.empty(); + temp_param.clear(); + } + else + { + break; + } + } + +return !function.parameters.empty(); } @@ -534,13 +524,14 @@ return !function.params.empty(); bool PatternParser::ReadFunction(Item::Function & function) { SkipWhite(); - - function.name.clear(); - function.params.clear(); + function.Clear(); if( !ReadName(function.name) ) return false; + if( IsPositiveNumber(function.name) ) + function.arg = wcstol(function.name.c_str(), 0, 10); + ReadParams(function); return true; @@ -556,8 +547,7 @@ bool PatternParser::ReadFunctions(Item & item) while( ReadFunction(temp_function) ) item.functions.push_back(temp_function); - temp_function.name.clear(); - temp_function.params.clear(); + temp_function.Clear(); return !item.functions.empty(); } @@ -667,11 +657,25 @@ void PatternParser::ReadDirectiveIsno(Item & item) +void PatternParser::ReadDirectiveEnd(Item & item) +{ + item.type = Item::item_end; +} + + + +void PatternParser::ReadDirectiveElse(Item & item) +{ + item.type = Item::item_else; +} + + + void PatternParser::ReadDirectiveIfindex(Item & item) { item.type = Item::item_err; item.functions.clear(); - temp_function.params.clear(); + temp_function.Clear(); // reading: odd, even, first or a number (without quotes) if( !ReadName(temp_function.name) ) @@ -724,24 +728,23 @@ void PatternParser::ReadDirectiveDef(Item & item) item.type = Item::item_err; ReadFunctions(item); - if( item.functions.size() == 1 ) + if( item.functions.size() == 1 && item.functions[0].parameters.size() == 1 ) { - if( item.functions[0].params.size() == 1 ) - { - // this is: [def variable "value"] - item.type = Item::item_def; - } + // it is [def name "value"] + // or [def name [otherfunction]] + // or [def name [otherfunction "argument"]] etc. + + item.type = Item::item_def; } else - if( item.functions.size() == 2 ) + if( item.functions.size() == 2 && + item.functions[0].parameters.empty() && item.functions[1].parameters.empty() ) { - if( item.functions[0].params.empty() && item.functions[1].params.empty()) - { - // this is: - // [def variable2 variable1], or - // [def function2 function1] - item.type = Item::item_def; - } + // it is an alias: + // [def name function] + // (name is an alias to a function, to a block or to an other variable) + + item.type = Item::item_def; } } @@ -762,14 +765,30 @@ void PatternParser::ReadDirectiveEzc(Item & item) ReadFunctions(item); } +void PatternParser::ReadDirectiveBlock(Item & item) +{ + item.type = Item::item_block; + ReadFunctions(item); + + // only one function without arguments + if( item.functions.size() != 1 || !item.functions[0].parameters.empty() ) + item.type = Item::item_err; +} + // user defined directive void PatternParser::ReadDirectiveNormal(const std::wstring & name, Item & item) { - temp_function.name = name; + temp_function.Clear(); ReadParams(temp_function); + temp_function.name = name; + + if( IsPositiveNumber(name) ) + temp_function.arg = wcstol(name.c_str(), 0, 10); + item.functions.clear(); + item.functions.push_back(temp_function); item.type = Item::item_normal; } @@ -792,13 +811,14 @@ std::wstring name; else if( name == L"if-index" ) ReadDirectiveIfindex(item); else if( name == L"is" ) ReadDirectiveIs(item); else if( name == L"is-no" ) ReadDirectiveIsno(item); - else if( name == L"end" ) item.type = Item::item_end; - else if( name == L"else" ) item.type = Item::item_else; + else if( name == L"end" ) ReadDirectiveEnd(item); + else if( name == L"else" ) ReadDirectiveElse(item); else if( name == L"for" ) ReadDirectiveFor(item); else if( name == L"include" ) ReadDirectiveInclude(item); 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"block" ) ReadDirectiveBlock(item); else if( name == L"#" ) ReadDirectiveComment(item); else ReadDirectiveNormal(name, item); @@ -904,6 +924,21 @@ void PatternParser::CreateTreeReadIf(Item & item) +void PatternParser::CreateTreeReadBlock(Item & item) +{ +Item item_block; + + CreateTree(item_block); + + if( item_block.LastItemType() == Item::item_end ) + item_block.DeleteLastItem(); + + if( pblocks && item.functions.size()==1 ) + pblocks->Insert(item.functions[0].name, item_block); +} + + + void PatternParser::CreateTreeReadFor(Item & item) { Item * pitem = item.AddItem(); @@ -931,8 +966,12 @@ void PatternParser::CreateTree(Item & item) item.DeleteLastItem(); return; } + + if( pitem->type == Item::item_block ) + CreateTreeReadBlock(*pitem); } - while( pitem->type == Item::item_comment ); + while( pitem->type == Item::item_comment || + pitem->type == Item::item_block ); if( pitem->type == Item::item_end || pitem->type == Item::item_else ) return; @@ -954,6 +993,8 @@ void PatternParser::CreateTree(Item & item) if( pitem->type == Item::item_include ) CreateTreeReadInclude(*pitem); + + // item_def is ignored here } } diff --git a/src/patternparser.h b/src/patternparser.h index fe7b78c..9b95da1 100755 --- a/src/patternparser.h +++ b/src/patternparser.h @@ -39,8 +39,8 @@ #ifndef headerfile_ezc_patternparser #define headerfile_ezc_patternparser +#include "blocks.h" #include "pattern.h" -#include "stringconv.h" #include "utf8/utf8.h" #ifdef EZC_USE_WINIX_LOGGER @@ -83,11 +83,7 @@ public: void DeleteWhiteTextItems(bool del); void SetIncludeMax(int include_max); - // files and strings (only char* and std::string) are treated - // as UTF-8 - void UTF8(bool utf8); - - + void SetBlocks(Blocks & blocks); private: @@ -114,8 +110,7 @@ private: // we read from these directories only if they are not empty std::wstring directory, directory2; - - bool input_as_utf8; + int include_level, include_level_max; @@ -135,6 +130,7 @@ private: // temporary object for a EZC function Item::Function temp_function; + Blocks * pblocks; void ReadFile(const std::wstring & name, std::wstring & result); @@ -143,7 +139,6 @@ private: bool IsFileCorrect(const wchar_t * name); bool ReadFileFromDir(const std::wstring & dir, const wchar_t * name, std::wstring & result); void ReadFile(std::ifstream & file, std::wstring & result); - void ReadFileContent(std::ifstream & file, std::wstring & result); int ReadCharInText(); bool IsWhite(wchar_t c); @@ -168,6 +163,8 @@ private: void ReadDirectiveIfoneno(Item & item); void ReadDirectiveIs(Item & item); void ReadDirectiveIsno(Item & item); + void ReadDirectiveEnd(Item & item); + void ReadDirectiveElse(Item & item); void ReadDirectiveIfindex(Item & item); void ReadDirectiveFor(Item & item); void ReadDirectiveComment(Item & item); @@ -175,6 +172,7 @@ private: void ReadDirectiveDef(Item & item); void ReadDirectiveFilter(Item & item); void ReadDirectiveEzc(Item & item); + void ReadDirectiveBlock(Item & item); void ReadDirectiveNormal(const std::wstring & name, Item & item); void CreateTreeReadItemDirectiveCheckEnding(Item & item); @@ -182,6 +180,7 @@ private: void CreateTreeReadItemText(Item & item); bool CreateTreeReadItem(Item & item); void CreateTreeReadIf(Item & item); + void CreateTreeReadBlock(Item & item); void CreateTreeReadFor(Item & item); void CreateTree(Item & item); void CreateTreeReadInclude(Item & item); diff --git a/src/vars.cpp b/src/vars.cpp new file mode 100644 index 0000000..43d3f15 --- /dev/null +++ b/src/vars.cpp @@ -0,0 +1,43 @@ +#include "vars.h" + + +namespace Ezc +{ + + +void Vars::Insert(const std::wstring & name, VariableType type, const std::wstring & value) +{ +Variable variable; + + variable.type = type; + variable.val = value; + + vars_tab[name] = variable; +} + + +Vars::Iterator Vars::Find(const std::wstring & name) +{ + return vars_tab.find(name); +} + + +Vars::Iterator Vars::Begin() +{ + return vars_tab.begin(); +} + + +Vars::Iterator Vars::End() +{ + return vars_tab.end(); +} + + +size_t Vars::Size() +{ + return vars_tab.size(); +} + + +} // namespace diff --git a/src/vars.h b/src/vars.h new file mode 100644 index 0000000..cb26644 --- /dev/null +++ b/src/vars.h @@ -0,0 +1,87 @@ +/* + * This file is a part of EZC -- Easy templating in C++ + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2014, 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_vars +#define headerfile_ezc_vars + +#include +#include + + + +namespace Ezc +{ + + + +class Vars +{ +public: + + enum VariableType + { + variable_string, + variable_alias + }; + + struct Variable + { + VariableType type; + std::wstring val; + }; + + typedef std::map VariablesTable; + typedef VariablesTable::iterator Iterator; + + void Insert(const std::wstring & name, VariableType type, const std::wstring & value); + + Iterator Find(const std::wstring & name); + + Iterator Begin(); + Iterator End(); + size_t Size(); + void Clear(); + +private: + + VariablesTable vars_tab; + +}; + +} // namespace + +#endif