replace slow entity parsing code

This commit is contained in:
Glenn Maynard
2005-09-04 23:05:58 +00:00
parent 7a561fc4d5
commit 852558eb06
2 changed files with 48 additions and 161 deletions
+47 -134
View File
@@ -22,15 +22,40 @@ static const char chXMLExclamation = '!';
static const char chXMLDash = '-';
static const XENTITY x_EntityTable[] = {
{ '&', "&", 5 } ,
{ '\"', """, 6 } ,
{ '\'', "'", 6 } ,
{ '<', "&lt;", 4 } ,
{ '>', "&gt;", 4 }
static map<CString,CString> g_mapEntitiesToChars;
static map<char,CString> g_mapCharsToEntities;
static void InitEntities()
{
if( !g_mapEntitiesToChars.empty() )
return;
struct Entity
{
char c;
const char *pEntity;
}
static const EntityTable[] =
{
{ '&', "amp", },
{ '\"', "quot", },
{ '\'', "apos", },
{ '<', "lt", },
{ '>', "gt", }
};
XENTITYS entityDefault(x_EntityTable, sizeof(x_EntityTable)/sizeof(x_EntityTable[0]) );
for( unsigned i = 0; i < ARRAYSIZE(EntityTable); ++i )
{
const Entity &ent = EntityTable[i];
g_mapEntitiesToChars[ent.pEntity] = CString(1, ent.c);
g_mapCharsToEntities[ent.c] = ent.pEntity;
}
}
struct RunInitEntities
{
RunInitEntities() { InitEntities(); }
} static g_RunInitEntities;
// skip spaces
static char* tcsskip( const char* psz )
@@ -249,8 +274,8 @@ const char* XNode::LoadAttributes( const char* xml, PARSEINFO *pi /*= &piDefault
SetString( xml, pEnd, &attr->m_sValue, trim, escape );
xml = pEnd;
// ATTRVALUE
if( pi->entity_value && pi->entitys )
attr->m_sValue = pi->entitys->Ref2Entity(attr->m_sValue);
if( pi->entity_value )
ReplaceEntityText( attr->m_sValue, g_mapEntitiesToChars );
if( quote == '"' || quote == '\'' )
xml++;
@@ -383,8 +408,8 @@ const char* XNode::Load( const char* xml, PARSEINFO *pi /*= &piDefault*/ )
xml = pEnd;
// TEXTVALUE reference
if( pi->entity_value && pi->entitys )
m_sValue = pi->entitys->Ref2Entity(m_sValue);
if( pi->entity_value )
ReplaceEntityText( m_sValue, g_mapEntitiesToChars );
}
// generate child nodes
@@ -477,8 +502,8 @@ const char* XNode::Load( const char* xml, PARSEINFO *pi /*= &piDefault*/ )
xml = pEnd;
//TEXTVALUE
if( pi->entity_value && pi->entitys )
m_sValue = pi->entitys->Ref2Entity(m_sValue);
if( pi->entity_value )
ReplaceEntityText( m_sValue, g_mapEntitiesToChars );
}
}
}
@@ -490,7 +515,10 @@ const char* XNode::Load( const char* xml, PARSEINFO *pi /*= &piDefault*/ )
// Return : converted plain string
bool XAttr::GetXML( RageFileBasic &f, DISP_OPT *opt ) const
{
return f.Write(m_sName + "='" + (opt && opt->reference_value && opt->entitys ? opt->entitys->Entity2Ref(m_sValue) : m_sValue) + "' ") != -1;
CString s(m_sValue);
if( opt && opt->reference_value )
ReplaceEntityText( s, g_mapCharsToEntities );
return f.Write(m_sName + "='" + s + "' ") != -1;
}
// Desc : convert plain xml text from parsed xml node
@@ -542,7 +570,7 @@ bool XNode::GetXML( RageFileBasic &f, DISP_OPT *opt ) const
return false;
// Text Value
if( m_sValue != ("") )
if( !m_sValue.empty() )
{
if( opt && opt->newline && !m_childs.empty() )
{
@@ -554,7 +582,10 @@ bool XNode::GetXML( RageFileBasic &f, DISP_OPT *opt ) const
if( f.Write("\t") == -1 )
return false;
}
if( f.Write((opt && opt->reference_value && opt->entitys ? opt->entitys->Entity2Ref(m_sValue) : m_sValue)) == -1 )
CString s( m_sValue );
if( opt && opt->reference_value )
ReplaceEntityText( s, g_mapCharsToEntities );
if( f.Write(s) == -1 )
return false;
}
@@ -729,124 +760,6 @@ void XNode::SetAttrValue( const CString &sName, const CString &sValue )
}
XENTITYS::XENTITYS( const XENTITY *entities, int count )
{
for( int i = 0; i < count; i++)
push_back( entities[i] );
}
const XENTITY *XENTITYS::GetEntity( char entity ) const
{
for( unsigned i = 0 ; i < size(); i ++ )
{
if( at(i).entity == entity )
return &at(i);
}
return NULL;
}
const XENTITY *XENTITYS::GetEntity( const char* entity ) const
{
for( unsigned i = 0 ; i < size(); i ++ )
{
const char* ref = at(i).ref;
const char* ps = entity;
while( ref && *ref )
if( *ref++ != *ps++ )
break;
if( ref && !*ref ) // found!
return &at(i);
}
return NULL;
}
int XENTITYS::GetEntityCount( const char* str ) const
{
int nCount = 0;
while( str && *str )
if( GetEntity(*str++) )
++nCount;
return nCount;
}
int XENTITYS::Ref2Entity( const char* pes, char* str, int len ) const
{
char* ps = str;
char* ps_end = ps+len;
while( pes && *pes && ps < ps_end )
{
const XENTITY *ent = GetEntity( pes );
if( ent )
{
// copy entity meanning char
*ps = ent->entity;
pes += ent->ref_len;
}
else
*ps = *pes++; // default character copy
ps++;
}
*ps = '\0';
// total copied characters
return ps-str;
}
int XENTITYS::Entity2Ref( const char* ps, char* estr, int estrlen ) const
{
char* pes = estr;
char* pes_end = pes+estrlen;
while( ps && *ps && pes < pes_end )
{
const XENTITY *ent = GetEntity( *ps );
if( ent )
{
// copy entity string
const char* ref = ent->ref;
while( ref && *ref )
*pes++ = *ref++;
}
else
*pes++ = *ps; // default character copy
ps++;
}
*pes = '\0';
// total copied characters
return pes-estr;
}
CString XENTITYS::Ref2Entity( const char* estr ) const
{
CString es;
if( estr )
{
int len = strlen(estr);
char* szTemp = new char[len+1];
int iLen = Ref2Entity( estr, szTemp, len );
es.assign( szTemp, iLen );
delete [] szTemp;
}
return es;
}
CString XENTITYS::Entity2Ref( const char* str ) const
{
CString s;
if( str )
{
int nEntityCount = GetEntityCount(str);
if( nEntityCount == 0 )
return CString(str);
int len = strlen(str) + nEntityCount*10;
char* szTemp = new char[len+1];
int iLen = Entity2Ref( str, szTemp, len );
s.assign( szTemp, iLen );
delete [] szTemp;
}
return s;
}
bool XNode::LoadFromFile( const CString &sFile )
{
RageFile f;
+1 -27
View File
@@ -57,29 +57,6 @@ typedef multimap<CString,XNode*> XNodes;
++Var##Iter, Var = Var##Iter->second )
// Entity Encode/Decode Support
struct XENTITY
{
char entity; // entity ( & " ' < > )
char ref[10]; // entity reference ( &amp; &quot; etc )
int ref_len; // entity reference length
};
struct XENTITYS : public vector<XENTITY>
{
const XENTITY *GetEntity( char entity ) const;
const XENTITY *GetEntity( const char* entity ) const;
int GetEntityCount( const char* str ) const;
int Ref2Entity( const char* estr, char* str, int strlen ) const;
int Entity2Ref( const char* str, char* estr, int estrlen ) const;
CString Ref2Entity( const char* estr ) const;
CString Entity2Ref( const char* str ) const;
XENTITYS(){};
XENTITYS( const XENTITY *entities, int count );
};
extern XENTITYS entityDefault;
enum PCODE
{
PIE_PARSE_WELL_FORMED = 0,
@@ -95,7 +72,6 @@ struct PARSEINFO
{
bool trim_value; // [set] do trim when parse?
bool entity_value; // [set] do convert from reference to entity? ( &lt; -> < )
XENTITYS *entitys; // [set] entity table for entity decode
char escape_value; // [set] escape value (default '\\')
char* xml; // [get] xml source
@@ -104,7 +80,7 @@ struct PARSEINFO
PCODE error_code; // [get] error code
CString error_string; // [get] error string
PARSEINFO() { trim_value = true; entity_value = true; entitys = &entityDefault; xml = NULL; error_occur = false; error_pointer = NULL; error_code = PIE_PARSE_WELL_FORMED; escape_value = 0; }
PARSEINFO() { trim_value = true; entity_value = true; xml = NULL; error_occur = false; error_pointer = NULL; error_code = PIE_PARSE_WELL_FORMED; escape_value = 0; }
};
// display optional environment
@@ -112,7 +88,6 @@ struct DISP_OPT
{
bool newline; // newline when new tag
bool reference_value; // do convert from entity to reference ( < -> &lt; )
XENTITYS *entitys; // entity table for entity encode
CString stylesheet; // empty string = no stylesheet
bool write_tabs; // if false, don't write tab indent characters
@@ -121,7 +96,6 @@ struct DISP_OPT
{
newline = true;
reference_value = true;
entitys = &entityDefault;
stylesheet = "";
write_tabs = true;
tab_base = 0;