initial import
git-svn-id: svn://ttmath.org/publicrep/cgi/ezc/trunk@4 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
commit
700dcd0571
|
@ -0,0 +1,28 @@
|
|||
Copyright (c) 2006-2007, 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.
|
|
@ -0,0 +1,410 @@
|
|||
#include "ezc.h"
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Ezc
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
bool Ezc::ReadFile(const char * name)
|
||||
{
|
||||
std::ifstream file(name);
|
||||
|
||||
if( !file )
|
||||
{
|
||||
std::ostringstream buffer;
|
||||
buffer << "<!-- ezc: can't open: " << name << " -->";
|
||||
input = buffer.str();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::getline(file, input, '\0');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Ezc::Init()
|
||||
{
|
||||
}
|
||||
|
||||
Ezc::Ezc()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
void Ezc::CreateTree()
|
||||
{
|
||||
item_root.ClearTable();
|
||||
item_root.type = Item::item_container;
|
||||
|
||||
const char * pinput = input.c_str();
|
||||
item_root.CreateTree(pinput);
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string Ezc::MakeText()
|
||||
{
|
||||
output.clear();
|
||||
|
||||
item_root.MakeText(output, user_functions);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
void Ezc::Insert(const std::string & key, UserFunction ufunction)
|
||||
{
|
||||
user_functions.insert( std::make_pair(key, ufunction) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Ezc::Item
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
Ezc::Item * Ezc::Item::AddItem(const Ezc::Item & porg)
|
||||
{
|
||||
Item * pitem = new Item(porg);
|
||||
|
||||
item_table.push_back(pitem);
|
||||
|
||||
return pitem;
|
||||
}
|
||||
|
||||
|
||||
void Ezc::Item::ClearTable()
|
||||
{
|
||||
std::vector<Item*>::iterator i = item_table.begin();
|
||||
|
||||
for( ; i != item_table.end() ; ++i )
|
||||
delete *i;
|
||||
|
||||
item_table.clear();
|
||||
}
|
||||
|
||||
Ezc::Item::Item()
|
||||
{
|
||||
}
|
||||
|
||||
Ezc::Item::~Item()
|
||||
{
|
||||
ClearTable();
|
||||
}
|
||||
|
||||
Ezc::Item::ItemType Ezc::Item::LastItemType()
|
||||
{
|
||||
if( item_table.empty() )
|
||||
return item_none;
|
||||
|
||||
return item_table.back()->type;
|
||||
}
|
||||
|
||||
|
||||
bool Ezc::Item::ReadChar(const char * & itext, char & result)
|
||||
{
|
||||
if( *itext==0 || *itext=='[' || *itext==']' )
|
||||
return false;
|
||||
|
||||
|
||||
if( *itext == '\\' )
|
||||
{
|
||||
if( *(itext+1)=='\\' || *(itext+1)=='[' || *(itext+1)==']' )
|
||||
{
|
||||
result = *(++itext);
|
||||
++itext;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
result = *itext;
|
||||
++itext;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Ezc::Item::SkipWhiteCharacters(const char * & itext)
|
||||
{
|
||||
while( *itext==' ' || *itext=='\t' )
|
||||
++itext;
|
||||
}
|
||||
|
||||
|
||||
void Ezc::Item::ReadDirective(const char * & itext, std::string & directive)
|
||||
{
|
||||
directive.clear();
|
||||
|
||||
SkipWhiteCharacters(itext);
|
||||
|
||||
while( (*itext>='a' && *itext<='z') ||
|
||||
(*itext>='A' && *itext<='Z') ||
|
||||
(*itext>='0' && *itext<='9') ||
|
||||
*itext=='_' || *itext=='-' )
|
||||
{
|
||||
directive += *itext;
|
||||
|
||||
++itext;
|
||||
}
|
||||
}
|
||||
|
||||
void Ezc::Item::CreateTreeReadItemDirectiveCheckEnding(const char * & itext)
|
||||
{
|
||||
SkipWhiteCharacters(itext);
|
||||
|
||||
if( *itext != ']' )
|
||||
{
|
||||
type = item_err;
|
||||
|
||||
while( *itext!=0 && *itext!=']' )
|
||||
++itext;
|
||||
}
|
||||
|
||||
if( *itext == ']' )
|
||||
++itext;
|
||||
}
|
||||
|
||||
|
||||
void Ezc::Item::CreateTreeReadItemDirective(const char * & itext)
|
||||
{
|
||||
std::string directive;
|
||||
|
||||
++itext;
|
||||
directives.clear();
|
||||
|
||||
ReadDirective(itext,directive);
|
||||
|
||||
if( directive == "if-any" )
|
||||
{
|
||||
type = item_ifany;
|
||||
|
||||
while( true )
|
||||
{
|
||||
ReadDirective(itext,directive);
|
||||
|
||||
if( directive.empty() )
|
||||
break;
|
||||
|
||||
directives.push_back(directive);
|
||||
}
|
||||
}
|
||||
else
|
||||
if( directive == "end" )
|
||||
{
|
||||
type = item_end;
|
||||
}
|
||||
else
|
||||
if( directive == "else" )
|
||||
{
|
||||
type = item_else;
|
||||
}
|
||||
else
|
||||
{
|
||||
directives.push_back(directive);
|
||||
type = item_normal;
|
||||
}
|
||||
|
||||
CreateTreeReadItemDirectiveCheckEnding(itext);
|
||||
}
|
||||
|
||||
|
||||
void Ezc::Item::CreateTreeReadItemText(const char * & itext)
|
||||
{
|
||||
char c;
|
||||
|
||||
text.clear();
|
||||
|
||||
while( ReadChar(itext, c) )
|
||||
text += c;
|
||||
|
||||
type = item_text;
|
||||
}
|
||||
|
||||
|
||||
bool Ezc::Item::CreateTreeReadItem(const char * & itext)
|
||||
{
|
||||
|
||||
if( *itext == '[' )
|
||||
{
|
||||
CreateTreeReadItemDirective(itext);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if( *itext )
|
||||
{
|
||||
CreateTreeReadItemText(itext);
|
||||
return true;
|
||||
}
|
||||
|
||||
// the end of the string
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Ezc::Item::CreateTreeReadAll(const char * & itext)
|
||||
{
|
||||
Item item;
|
||||
|
||||
while( item.CreateTreeReadItem(itext) )
|
||||
{
|
||||
AddItem(item);
|
||||
|
||||
if( item.type==item_end || item.type==item_else )
|
||||
return;
|
||||
|
||||
if( item.type == Item::item_ifany )
|
||||
item_table.back()->CreateTreeReadIfany(itext);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Ezc::Item::CreateTreeReadIfany(const char * & itext)
|
||||
{
|
||||
Item item;
|
||||
|
||||
item.type = item_container;
|
||||
AddItem(item);
|
||||
item_table.back()->CreateTree(itext);
|
||||
|
||||
if( item_table.back()->LastItemType() == item_else )
|
||||
{
|
||||
// basically we don't have to erase it
|
||||
item_table.back()->item_table.erase(
|
||||
item_table.back()->item_table.begin() +
|
||||
item_table.back()->item_table.size() - 1 );
|
||||
|
||||
item.ClearTable();
|
||||
AddItem(item);
|
||||
item_table.back()->CreateTree(itext);
|
||||
}
|
||||
|
||||
if( item_table.back()->LastItemType() != item_end )
|
||||
{
|
||||
// [end] is missing
|
||||
// it's probably the end of the input string
|
||||
}
|
||||
else
|
||||
{
|
||||
// basically we don't have to do it
|
||||
item_table.back()->item_table.erase(
|
||||
item_table.back()->item_table.begin() +
|
||||
item_table.back()->item_table.size() - 1 );
|
||||
}
|
||||
}
|
||||
|
||||
void Ezc::Item::CreateTree(const char * & itext)
|
||||
{
|
||||
if( type == item_container)
|
||||
CreateTreeReadAll(itext);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
void Ezc::Item::MakeTextContainer(std::string & otext, UserFunctions & user_functions)
|
||||
{
|
||||
std::vector<Item*>::iterator i = item_table.begin();
|
||||
|
||||
for( ; i != item_table.end() ; ++i )
|
||||
(*i)->MakeText(otext, user_functions);
|
||||
}
|
||||
|
||||
|
||||
void Ezc::Item::MakeTextMsgCantFind(std::string & otext, std::string & key)
|
||||
{
|
||||
std::ostringstream msg;
|
||||
|
||||
msg << "<!-- ezc: can't find: " << key << " -->";
|
||||
otext += msg.str();
|
||||
}
|
||||
|
||||
|
||||
void Ezc::Item::MakeTextNormal(std::string & otext, UserFunctions & user_functions)
|
||||
{
|
||||
if( directives.empty() )
|
||||
return;
|
||||
|
||||
UserFunctions::iterator i = user_functions.find( directives[0] );
|
||||
|
||||
if( i != user_functions.end() )
|
||||
{
|
||||
EzcInfo info;
|
||||
(i->second)(info);
|
||||
|
||||
otext += info.text;
|
||||
}
|
||||
else
|
||||
{
|
||||
MakeTextMsgCantFind(otext, directives[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void Ezc::Item::MakeTextIfany(std::string & otext, UserFunctions & user_functions)
|
||||
{
|
||||
std::vector<std::string>::iterator d = directives.begin();
|
||||
int how_many_true = 0;
|
||||
|
||||
for( ; d != directives.end() ; ++d )
|
||||
{
|
||||
UserFunctions::iterator i = user_functions.find( *d );
|
||||
|
||||
if( i != user_functions.end() )
|
||||
{
|
||||
EzcInfo info;
|
||||
(i->second)(info);
|
||||
|
||||
if( info.result )
|
||||
++how_many_true;
|
||||
}
|
||||
else
|
||||
{
|
||||
MakeTextMsgCantFind(otext, *d);
|
||||
}
|
||||
}
|
||||
|
||||
if( how_many_true == directives.size() )
|
||||
{
|
||||
if( !item_table.empty() )
|
||||
item_table[0]->MakeText(otext, user_functions);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( item_table.size() > 1 )
|
||||
item_table[1]->MakeText(otext, user_functions);
|
||||
}
|
||||
}
|
||||
|
||||
void Ezc::Item::MakeText(std::string & otext, UserFunctions & user_functions)
|
||||
{
|
||||
if( type == item_text )
|
||||
{
|
||||
otext += text;
|
||||
}
|
||||
else
|
||||
if( type == item_container )
|
||||
{
|
||||
MakeTextContainer(otext, user_functions);
|
||||
}
|
||||
else
|
||||
if( type == item_normal )
|
||||
{
|
||||
MakeTextNormal(otext, user_functions);
|
||||
}
|
||||
else
|
||||
if( type == item_ifany )
|
||||
{
|
||||
MakeTextIfany(otext, user_functions);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
#ifndef headerfileezc
|
||||
#define headerfileezc
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
struct EzcInfo
|
||||
{
|
||||
std::string text;
|
||||
bool result;
|
||||
|
||||
EzcInfo()
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
};
|
||||
|
||||
class Ezc
|
||||
{
|
||||
public:
|
||||
typedef void (*UserFunction)(EzcInfo &);
|
||||
typedef std::map<std::string, UserFunction> UserFunctions;
|
||||
|
||||
UserFunctions user_functions;
|
||||
|
||||
Ezc();
|
||||
void Init();
|
||||
bool ReadFile(const char * name);
|
||||
void CreateTree();
|
||||
std::string MakeText();
|
||||
void Insert(const std::string & key, UserFunction ufunction);
|
||||
|
||||
private:
|
||||
struct Item
|
||||
{
|
||||
enum ItemType
|
||||
{
|
||||
item_none, item_container, item_text, item_ifany, item_for, item_else,
|
||||
item_end, item_err, item_normal
|
||||
};
|
||||
|
||||
ItemType type;
|
||||
std::string text;
|
||||
std::vector<Item*> item_table;
|
||||
|
||||
std::vector<std::string> directives;
|
||||
|
||||
Item();
|
||||
~Item();
|
||||
Item * AddItem(const Item & porg);
|
||||
void SkipWhiteCharacters(const char * & itext);
|
||||
void ReadDirective(const char * & itext, std::string & directive);
|
||||
void ClearTable();
|
||||
ItemType LastItemType();
|
||||
bool ReadChar(const char * & itext, char & result);
|
||||
void CreateTreeReadItemDirectiveCheckEnding(const char * & itext);
|
||||
void CreateTreeReadItemDirective(const char * & itext);
|
||||
void CreateTreeReadItemText(const char * & itext);
|
||||
bool CreateTreeReadItem(const char * & itext);
|
||||
void CreateTreeReadAll(const char * & itext);
|
||||
void CreateTreeReadIfany(const char * & itext);
|
||||
void CreateTree(const char * & itext);
|
||||
|
||||
void MakeTextIfany(std::string & otext, UserFunctions & user_functions);
|
||||
void MakeTextContainer(std::string & otext, UserFunctions & user_functions);
|
||||
void MakeTextMsgCantFind(std::string & otext, std::string & key);
|
||||
void MakeTextNormal(std::string & otext, UserFunctions & user_functions);
|
||||
|
||||
void MakeText(std::string & otext,UserFunctions & user_functions);
|
||||
};
|
||||
|
||||
Item item_root;
|
||||
std::string input;
|
||||
std::string output;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue