initial import

git-svn-id: svn://ttmath.org/publicrep/cgi/ezc/trunk@4 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
2007-01-24 20:01:55 +00:00
commit 700dcd0571
3 changed files with 519 additions and 0 deletions

410
src/ezc.cpp Normal file
View File

@@ -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);
}
}

81
src/ezc.h Normal file
View File

@@ -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