From fd75a1f119e6d9de4046a9792584bc716c88c902 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Sat, 11 Oct 2014 19:01:17 +0000 Subject: [PATCH] copied: pattern.cpp -> patternparser.cpp git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@968 e52654a7-88a9-db11-a3e9-0013d4bc506e --- src/patternparser.cpp | 1049 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1049 insertions(+) create mode 100755 src/patternparser.cpp diff --git a/src/patternparser.cpp b/src/patternparser.cpp new file mode 100755 index 0000000..f5f0518 --- /dev/null +++ b/src/patternparser.cpp @@ -0,0 +1,1049 @@ +/* + * This file is a part of EZC -- Easy templating in C++ + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2007-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. + */ + + +#include "pattern.h" + + + +namespace Ezc +{ + + + +Pattern::Pattern() +{ + Clear(); + + commentary_start = L""; + + allow_include = true; + input_as_utf8 = true; + delete_white_text_items = false; + + include_level_max = 100; +} + + + +void Pattern::Clear() +{ + item_root.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]); +} + + + +void Pattern::Directory(const char * dir, const char * dir2) +{ + directory.clear(); + directory2.clear(); + + if( dir ) + PT::UTF8ToWide(dir, directory); + + if( dir2 ) + PT::UTF8ToWide(dir2, directory2); +} + + + +void Pattern::Directory(const std::string & dir) +{ + PT::UTF8ToWide(dir, directory); + directory2.clear(); +} + + + +void Pattern::Directory(const std::string & dir, const std::string & dir2) +{ + PT::UTF8ToWide(dir, directory); + PT::UTF8ToWide(dir2, directory2); +} + + + +void Pattern::Directory(const wchar_t * dir, const wchar_t * dir2) +{ + directory.clear(); + directory2.clear(); + + if( dir ) + directory = dir; + + if( dir2 ) + directory2 = dir2; +} + + + +void Pattern::Directory(const std::wstring & dir) +{ + directory = dir; + directory2.clear(); +} + + + +void Pattern::Directory(const std::wstring & dir, const std::wstring & dir2) +{ + directory = dir; + directory2 = dir2; +} + + + +void Pattern::ParseFile(const std::string & file_name) +{ + ParseFile( file_name.c_str() ); +} + + + + +void Pattern::ParseFile(const char * file_name) +{ + PT::UTF8ToWide(file_name, item_root.file_name); + include_level = 0; + CreateTreeReadIncludeSkipAllowFlag(item_root); +} + + + + +void Pattern::ParseFile(const std::wstring & file_name) +{ + ParseFile( file_name.c_str() ); +} + + + + +void Pattern::ParseFile(const wchar_t * file_name) +{ + item_root.file_name = file_name; + include_level = 0; + CreateTreeReadIncludeSkipAllowFlag(item_root); +} + + + + +void Pattern::ParseString(const char * str) +{ + if( input_as_utf8 ) + PT::UTF8ToWide(str, string_content); + else + AssignString(str, string_content); + + ParseString(string_content.c_str()); + string_content.clear(); +} + + + +void Pattern::ParseString(const std::string & str) +{ + ParseString(str.c_str()); +} + + + + + + + + +void Pattern::ParseString(const wchar_t * str) +{ + itext = str; + include_level = 0; + CreateTree(item_root); +} + + + +void Pattern::ParseString(const std::wstring & str) +{ + ParseString(str.c_str()); +} + + + + + + + + + +void Pattern::AllowInclude(bool allow) +{ + allow_include = allow; +} + + + +void Pattern::DeleteWhiteTextItems(bool del) +{ + delete_white_text_items = del; +} + + + +void Pattern::SetIncludeMax(int include_max) +{ + include_level_max = include_max; +} + + + +void Pattern::UTF8(bool utf8) +{ + input_as_utf8 = utf8; +} + + + + + + +void Pattern::SetCommentary(const char * com_start, const char * com_stop) +{ + PT::UTF8ToWide(com_start, commentary_start); + PT::UTF8ToWide(com_stop, commentary_stop); +} + + + +void Pattern::SetCommentary(const std::string & com_start, const std::string & com_stop) +{ + PT::UTF8ToWide(com_start, commentary_start); + PT::UTF8ToWide(com_stop, commentary_stop); +} + + + +void Pattern::SetCommentary(const wchar_t * com_start, const wchar_t * com_stop) +{ + commentary_start = com_start; + commentary_stop = com_stop; +} + + + +void Pattern::SetCommentary(const std::wstring & com_start, const std::wstring & com_stop) +{ + commentary_start = com_start; + commentary_stop = com_stop; +} + + + + + +void Pattern::CreateMsg(std::wstring & out, const wchar_t * type, const wchar_t * arg) +{ + out = commentary_start; + out += L"Ezc: "; + out += type; + + if( arg ) + { + out += ' '; + out += arg; + } + + out += commentary_stop; +} + + + + + + + +bool Pattern::HasFileAtBeginning(const wchar_t * path, const wchar_t * file) +{ + for(; *path && *file; ++path, ++file) + { + if( *path != *file ) + return false; + } + + if( *file != 0 ) + return false; + + // "\" is from a dos path syntax + if( *path==0 || *path=='\\' || *path=='/' ) + return true; + +return false; +} + + +/* + ".." is not allowed in the file path + you cannot go up from your template directory +*/ +bool Pattern::IsFileCorrect(const wchar_t * name) +{ + while( *name ) + { + if( HasFileAtBeginning(name, L"..") ) + return false; + + // looking for the next slash of backslash + while( *name && *name!='\\' && *name!='/' ) + name += 1; + + // skipping the slash (or backslash) + if( *name ) + name += 1; + } + +return true; +} + + + + +/* + 'name' must be a relative path - without a slash or backslash +*/ +void Pattern::ReadFile(const std::wstring & name, std::wstring & result) +{ + ReadFile(name.c_str(), result); +} + + +/* + 'name' must be a relative path - without a slash or backslash +*/ +void Pattern::ReadFile(const wchar_t * name, std::wstring & result) +{ + if( !IsFileCorrect(name) ) + { + CreateMsg(result, L"incorrect file name: ", name); + } + else + { + result.clear(); + + if( !ReadFileFromDir(directory, name, result) ) + if( !ReadFileFromDir(directory2, name, result) ) + CreateMsg(result, L"can't open: ", name); + } +} + + + +bool Pattern::ReadFileFromDir(const std::wstring & dir, const wchar_t * name, std::wstring & result) +{ + if( dir.empty() ) + return false; + + file_name = dir; + file_name += '/'; + file_name += name; + PT::WideToUTF8(file_name, afile_name); + + std::ifstream file(afile_name.c_str()); + + if( !file ) + { + file_name.clear(); + afile_name.clear(); + return false; + } + + #ifdef EZC_USE_WINIX_LOGGER + if( include_level <= 1 ) + Winix::log << Winix::log3 << "Ezc: reading pattern: " << afile_name << Winix::logend; + else + Winix::log << Winix::log3 << " including pattern: " << afile_name << Winix::logend; + #endif + + ReadFile(file, result); + + file_name.clear(); + afile_name.clear(); + +return true; +} + + + + +void Pattern::ReadFile(std::ifstream & file, std::wstring & result) +{ + if( input_as_utf8 ) + { + PT::UTF8ToWide(file, result); + } + else + { + ReadFileContent(file, result); + } +} + + + + +void Pattern::ReadFileContent(std::ifstream & file, std::wstring & result) +{ + while( true ) + { + int c = file.get(); + + if( !file ) + break; + + result += static_cast(c); + } +} + + + + +int Pattern::ReadCharInText() +{ + if( *itext==0 || *itext=='[' ) + return -1; + + if( *itext == '\\' ) + { + if( *(itext+1)=='\\' || *(itext+1)=='[' || *(itext+1)==']' ) + ++itext; + } + +return *(itext++); +} + + +bool Pattern::IsWhite(wchar_t c) +{ + // 13 (\r) is from a dos file at the end of a line (\r\n) + // 160 is a non-breaking space + + if( c==' ' || c=='\t' || c==13 || c==160 || c==10 ) + return true; + +return false; +} + + + +void Pattern::SkipWhite() +{ + while( IsWhite(*itext) ) + ++itext; +} + + + +void Pattern::CheckWhiteAndDelete(std::wstring & s) +{ +size_t i; + + if( s.empty() ) + return; + + for(i=0 ; i='a' && c<='z') || + (c>='A' && c<='Z') || + (c>='0' && c<='9') || + c=='_' || c=='-' || c=='.' || c=='#'); +} + + + +bool Pattern::IsDigit(wchar_t c) +{ + return (c>='0' && c<='9'); +} + + + +bool Pattern::IsPositiveNumber(const std::wstring & str) +{ +size_t i; + + for(i=0 ; i(c); + + if( delete_white_text_items ) + CheckWhiteAndDelete(item.text); + + item.type = Item::item_text; +} + + + +bool Pattern::CreateTreeReadItem(Item & item) +{ + item.Clear(); + + if( *itext == '[' ) + { + CreateTreeReadItemDirective(item); + return true; + } + else + if( *itext ) + { + CreateTreeReadItemText(item); + return true; + } + +// the end of the string +return false; +} + + + + + +void Pattern::CreateTreeReadInclude(Item & item) +{ + if( !allow_include ) + return; + + CreateTreeReadIncludeSkipAllowFlag(item); +} + + + + +void Pattern::CreateTreeReadIncludeSkipAllowFlag(Item & item) +{ + if( item.file_name.empty() ) + return; + + if( include_level > include_level_max ) + { + #ifdef EZC_USE_WINIX_LOGGER + Winix::log << Winix::log1 << "Ezc: \"include\" directive has reached the maximum level" << Winix::logend; + #endif + + return; + } + + ++include_level; + std::wstring file_text; // this temporary object must not be global (includes can be nested) + ReadFile(item.file_name, file_text); + + const wchar_t * itext_old = itext; + itext = file_text.c_str(); + CreateTree(item); + itext = itext_old; + --include_level; +} + + + +void Pattern::CreateTreeReadIf(Item & item) +{ + Item * pitem = item.AddItem(); + CreateTree(*pitem); + + if( pitem->LastItemType() == Item::item_else ) + { + pitem->DeleteLastItem(); + + pitem = item.AddItem(); + CreateTree(*pitem); + } + + if( pitem->LastItemType() == Item::item_end ) + pitem->DeleteLastItem(); +} + + + +void Pattern::CreateTreeReadFor(Item & item) +{ + Item * pitem = item.AddItem(); + CreateTree(*pitem); + + if( pitem->LastItemType() == Item::item_end ) + pitem->DeleteLastItem(); +} + + + +void Pattern::CreateTree(Item & item) +{ + item.Clear(); + item.type = Item::item_container; + + while( true ) + { + Item * pitem = item.AddItem(); + + do + { + if( !CreateTreeReadItem(*pitem) ) + { + item.DeleteLastItem(); + return; + } + } + while( pitem->type == Item::item_comment ); + + if( pitem->type == Item::item_end || pitem->type == Item::item_else ) + return; + + if( pitem->type == Item::item_if || + pitem->type == Item::item_ifno || + pitem->type == Item::item_ifany || + pitem->type == Item::item_ifone || + pitem->type == Item::item_ifanyno || + pitem->type == Item::item_ifoneno || + pitem->type == Item::item_ifindex || + pitem->type == Item::item_is || + pitem->type == Item::item_isno ) + CreateTreeReadIf(*pitem); + + if( pitem->type == Item::item_for || + pitem->type == Item::item_filter ) + CreateTreeReadFor(*pitem); + + if( pitem->type == Item::item_include ) + CreateTreeReadInclude(*pitem); + } +} + + + + + + +} // namespace Ezc + + +