/***************************************************************************
* Copyright (C) 2004 by Tomas Mecir *
* kmuddy@kmuddy.org *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Library General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
***************************************************************************/
#include "centitymanager.h"
#include "entitylist.h"
cEntityManager::cEntityManager (bool noStdEntities)
{
reset (noStdEntities);
}
cEntityManager::~cEntityManager ()
{
entities.clear ();
}
void cEntityManager::reset (bool noStdEntities)
{
partent = "";
entities.clear ();
inEntity = false;
if (noStdEntities)
return;
char s[2];
s[1] = 0;
//restore standard HTML entities
for (int i = 0; i < NUM_MXP_ENTITIES; i++)
{
s[0] = ENTITY_DEF[i];
entities[ENTITY_NAMES[i]] = s;
}
}
//can this be the first letter of an entity?
inline bool correct1 (char l)
{
return (((l >= 'a') && (l <= 'z')) || ((l >= 'A') && (l <= 'Z')) || (l == '#'));
}
//can this be a letter of entity?
inline bool correctN (char l)
{
return (((l >= 'a') && (l <= 'z')) || ((l >= 'A') && (l <= 'Z')) || (l == '_') ||
((l >= '0') && (l <= '9')));
}
void cEntityManager::addEntity (const string &name, const string &value)
{
if (name.empty()) return;
//add or modify the entity
entities[name] = value;
}
void cEntityManager::deleteEntity (const string &name)
{
entities.erase (name);
}
string cEntityManager::entity (const string &name)
{
if (exists (name))
return entities[name];
//return empty string otherwise
return empty_string;
}
string cEntityManager::expandEntities (const string &s, bool finished)
{
string s1;
if (!partent.empty ()) //some unfinished entity is waiting...
inEntity = true;
string::const_iterator it;
for (it = s.begin(); it != s.end(); ++it)
if (inEntity)
{
char ch = *it;
if (ch == ';') //end of entity
{
inEntity = false;
if (partent.empty()) //received &;
{
s1 += "&;";
}
else
if (partent[0] == '_') //invalid entity name - IGNORED
{
partent = "";
}
else
if (partent[0] == '#') //&#nnn; entity
{
//compute number
int n = 0;
string::iterator it2 = partent.begin();
it2++; //starting from second character
for (; it2 != partent.end(); ++it2)
{
int x = *it2 - 48;
if ((x < 0) || (x > 9)) //WRONG
{
n = 0;
break;
}
n = n * 10 + x;
if (n > 255) //number too big!
{
n = 0;
break;
}
}
//verify number, IGNORE entity if it's wrong
if ((n >= 32) && (n <= 255))
s1 += (unsigned char) n;
partent = "";
}
else
{
//now we have correct entity name, let's expand it, if possible :)
if (entities.count (partent))
s1 += entities[partent];
else
//keep the same string if the entity doesn't exist...
s1 += "&" + partent + ";";
partent = "";
}
}
else if (ch == '&')
//unterminated entity, new entity may start here
{
s1 += "&" + partent;
partent = "";
//isEntity remains set
}
else if ((partent.empty() && correct1(ch)) || ((!partent.empty()) && correctN(ch)))
{
partent += ch;
}
//this wasn't an entity after all
else
{
inEntity = false;
s1 += "&" + partent + ch;
partent = "";
}
}
else
{
if (*it == '&')
inEntity = true;
else
//copy without change
s1 += *it;
}
//string ends in an unterminated entity, but only if the string is finished
if (inEntity && finished)
{
s1 += "&" + partent;
partent = "";
inEntity = false;
}
//return the resulting string
return s1;
}
bool cEntityManager::needMoreText()
{
return partent.empty() ? false : true;
}
syntax highlighted by Code2HTML, v. 0.9.1