use CString
This commit is contained in:
+95
-95
@@ -57,12 +57,9 @@ struct RunInitEntities
|
|||||||
} static g_RunInitEntities;
|
} static g_RunInitEntities;
|
||||||
|
|
||||||
// skip spaces
|
// skip spaces
|
||||||
static char* tcsskip( const char* psz )
|
static void tcsskip( const CString &s, unsigned &i )
|
||||||
{
|
{
|
||||||
while( psz && isspace(*psz) )
|
i = s.find_first_not_of( " \t\r\n", i );
|
||||||
++psz;
|
|
||||||
|
|
||||||
return (char*)psz;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool XIsEmptyString( const CString &s )
|
static bool XIsEmptyString( const CString &s )
|
||||||
@@ -71,21 +68,21 @@ static bool XIsEmptyString( const CString &s )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// put string of (psz~end) on ps string
|
// put string of (psz~end) on ps string
|
||||||
static void SetString( const char* psz, const char* end, CString* ps, bool trim = false )
|
static void SetString( const CString &s, int iStart, int iEnd, CString* ps, bool trim = false )
|
||||||
{
|
{
|
||||||
if( trim )
|
if( trim )
|
||||||
{
|
{
|
||||||
while( psz < end && isspace(*psz) )
|
while( iStart < iEnd && isspace(s[iStart]) )
|
||||||
psz++;
|
iStart++;
|
||||||
while( end-1 >= psz && isspace(end[-1]) )
|
while( iEnd-1 >= iStart && isspace(s[iEnd-1]) )
|
||||||
end--;
|
iEnd--;
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = end - psz;
|
int len = iEnd - iStart;
|
||||||
if( len <= 0 )
|
if( len <= 0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ps->assign( psz, len );
|
ps->assign( s, iStart, len );
|
||||||
}
|
}
|
||||||
|
|
||||||
XNode::~XNode()
|
XNode::~XNode()
|
||||||
@@ -109,22 +106,23 @@ void XNode::Clear()
|
|||||||
// Desc : loading attribute plain xml text
|
// Desc : loading attribute plain xml text
|
||||||
// Param : pszAttrs - xml of attributes
|
// Param : pszAttrs - xml of attributes
|
||||||
// pi = parser information
|
// pi = parser information
|
||||||
// Return : advanced string pointer. (error return NULL)
|
// Return : advanced string pointer. (error return npos)
|
||||||
const char* XNode::LoadAttributes( const char* xml, PARSEINFO *pi /*= &piDefault*/)
|
unsigned XNode::LoadAttributes( const CString &xml, PARSEINFO *pi, unsigned iOffset )
|
||||||
{
|
{
|
||||||
while( xml && *xml )
|
while( iOffset < xml.size() )
|
||||||
{
|
{
|
||||||
xml = tcsskip( xml );
|
tcsskip( xml, iOffset );
|
||||||
if( !xml )
|
if( iOffset >= xml.size() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// close tag
|
// close tag
|
||||||
if( *xml == chXMLTagClose || *xml == chXMLTagPre || *xml == chXMLQuestion || *xml == chXMLDash )
|
if( iOffset < xml.size() &&
|
||||||
return xml; // well-formed tag
|
(xml[iOffset] == chXMLTagClose || xml[iOffset] == chXMLTagPre || xml[iOffset] == chXMLQuestion || xml[iOffset] == chXMLDash) )
|
||||||
|
return iOffset; // well-formed tag
|
||||||
|
|
||||||
// XML Attr Name
|
// XML Attr Name
|
||||||
const char* pEnd = strpbrk( xml, " =" );
|
unsigned iEnd = xml.find_first_of( " =", iOffset );
|
||||||
if( pEnd == NULL )
|
if( iEnd == xml.npos )
|
||||||
{
|
{
|
||||||
// error
|
// error
|
||||||
if( !pi->error_occur )
|
if( !pi->error_occur )
|
||||||
@@ -134,58 +132,59 @@ const char* XNode::LoadAttributes( const char* xml, PARSEINFO *pi /*= &piDefault
|
|||||||
pi->error_code = PIE_ATTR_NO_VALUE;
|
pi->error_code = PIE_ATTR_NO_VALUE;
|
||||||
pi->error_string = ssprintf( "<%s> attribute has error ", m_sName.c_str() );
|
pi->error_string = ssprintf( "<%s> attribute has error ", m_sName.c_str() );
|
||||||
}
|
}
|
||||||
return NULL;
|
return string.npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
XAttr *attr = new XAttr;
|
XAttr *attr = new XAttr;
|
||||||
|
|
||||||
// XML Attr Name
|
// XML Attr Name
|
||||||
SetString( xml, pEnd, &attr->m_sName );
|
SetString( xml, iOffset, iEnd, &attr->m_sName );
|
||||||
|
|
||||||
// add new attribute
|
// add new attribute
|
||||||
DEBUG_ASSERT( attr->m_sName.size() );
|
DEBUG_ASSERT( attr->m_sName.size() );
|
||||||
m_attrs.insert( make_pair(attr->m_sName, attr) );
|
m_attrs.insert( make_pair(attr->m_sName, attr) );
|
||||||
xml = pEnd;
|
iOffset = iEnd;
|
||||||
|
|
||||||
// XML Attr Value
|
// XML Attr Value
|
||||||
xml = tcsskip( xml );
|
tcsskip( xml, iOffset );
|
||||||
if( !xml )
|
|
||||||
|
if( iOffset < xml.size() && xml[iOffset] == '=' )
|
||||||
|
{
|
||||||
|
++iOffset;
|
||||||
|
|
||||||
|
tcsskip( xml, iOffset );
|
||||||
|
if( iOffset >= xml.size() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
//if( xml = strchr( xml, '=' ) )
|
|
||||||
if( *xml == '=' )
|
|
||||||
{
|
|
||||||
xml = tcsskip( ++xml );
|
|
||||||
if( !xml )
|
|
||||||
continue;
|
|
||||||
// if " or '
|
// if " or '
|
||||||
// or none quote
|
// or none quote
|
||||||
int quote = *xml;
|
char quote = xml[iOffset];
|
||||||
if( quote == '"' || quote == '\'' )
|
if( quote == '"' || quote == '\'' )
|
||||||
{
|
{
|
||||||
pEnd = strchr( ++xml, quote );
|
++iOffset;
|
||||||
|
iEnd = xml.find( quote, iOffset );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//attr= value>
|
//attr= value>
|
||||||
// none quote mode
|
// none quote mode
|
||||||
pEnd = strpbrk( xml, " >" );
|
iEnd = xml.find_first_of( " >", iOffset );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool trim = pi->trim_value;
|
bool trim = pi->trim_value;
|
||||||
SetString( xml, pEnd, &attr->m_sValue, trim );
|
SetString( xml, iOffset, iEnd, &attr->m_sValue, trim );
|
||||||
xml = pEnd;
|
iOffset = iEnd;
|
||||||
// ATTRVALUE
|
// ATTRVALUE
|
||||||
if( pi->entity_value )
|
if( pi->entity_value )
|
||||||
ReplaceEntityText( attr->m_sValue, g_mapEntitiesToChars );
|
ReplaceEntityText( attr->m_sValue, g_mapEntitiesToChars );
|
||||||
|
|
||||||
if( quote == '"' || quote == '\'' )
|
if( quote == '"' || quote == '\'' )
|
||||||
xml++;
|
++iOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// not well-formed tag
|
// not well-formed tag
|
||||||
return NULL;
|
return string::npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// <TAG attr1="value1" attr2='value2' attr3=value3 >
|
// <TAG attr1="value1" attr2='value2' attr3=value3 >
|
||||||
@@ -196,28 +195,28 @@ const char* XNode::LoadAttributes( const char* xml, PARSEINFO *pi /*= &piDefault
|
|||||||
// Desc : load xml plain text
|
// Desc : load xml plain text
|
||||||
// Param : pszXml - plain xml text
|
// Param : pszXml - plain xml text
|
||||||
// pi = parser information
|
// pi = parser information
|
||||||
// Return : advanced string pointer (error return NULL)
|
// Return : advanced string pointer (error return npos)
|
||||||
const char* XNode::Load( const char* xml, PARSEINFO *pi /*= &piDefault*/ )
|
unsigned XNode::Load( const CString &xml, PARSEINFO *pi, unsigned iOffset )
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
|
|
||||||
// <
|
// <
|
||||||
xml = strchr( xml, chXMLTagOpen );
|
iOffset = xml.find( chXMLTagOpen, iOffset );
|
||||||
if( xml == NULL )
|
if( iOffset == string.npos )
|
||||||
return NULL;
|
return string.npos;
|
||||||
|
|
||||||
// </
|
// </
|
||||||
if( xml[1] == chXMLTagPre )
|
if( xml[iOffset+1] == chXMLTagPre )
|
||||||
return xml;
|
return iOffset;
|
||||||
|
|
||||||
/* <!-- */
|
/* <!-- */
|
||||||
if( !strncmp(xml+1, "!--", 3) )
|
if( !xml.compare(iOffset+1, 3, "!--") )
|
||||||
{
|
{
|
||||||
xml += 4;
|
iOffset += 4;
|
||||||
|
|
||||||
/* Find the close tag. */
|
/* Find the close tag. */
|
||||||
char *pEnd = strstr( xml, "-->" );
|
unsigned iEnd = xml.find( "-->" );
|
||||||
if( pEnd == NULL )
|
if( iEnd == string.npos )
|
||||||
{
|
{
|
||||||
if( !pi->error_occur )
|
if( !pi->error_occur )
|
||||||
{
|
{
|
||||||
@@ -227,38 +226,38 @@ const char* XNode::Load( const char* xml, PARSEINFO *pi /*= &piDefault*/ )
|
|||||||
pi->error_string = "Unterminated comment";
|
pi->error_string = "Unterminated comment";
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return string.npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip -->.
|
// Skip -->.
|
||||||
xml = pEnd + 3;
|
iOffset = iEnd + 3;
|
||||||
|
|
||||||
return Load( xml, pi );
|
return Load( xml, pi, iOffset );
|
||||||
}
|
}
|
||||||
|
|
||||||
// XML Node Tag Name Open
|
// XML Node Tag Name Open
|
||||||
xml++;
|
iOffset++;
|
||||||
const char* pTagEnd = strpbrk( xml, " \t\r\n/>" );
|
unsigned iTagEnd = xml.find_first_of( " \t\r\n/>", iOffset );
|
||||||
SetString( xml, pTagEnd, &m_sName );
|
SetString( xml, iOffset, iTagEnd, &m_sName );
|
||||||
|
iOffset = iTagEnd;
|
||||||
|
|
||||||
xml = pTagEnd;
|
|
||||||
// Generate XML Attributte List
|
// Generate XML Attributte List
|
||||||
xml = LoadAttributes( xml, pi );
|
iOffset = LoadAttributes( xml, pi, iOffset );
|
||||||
if( xml == NULL )
|
if( iOffset == string.npos )
|
||||||
return NULL;
|
return string.npos;
|
||||||
|
|
||||||
// alone tag <TAG ... /> or <?TAG ... ?> or <!-- ... -->
|
// alone tag <TAG ... /> or <?TAG ... ?> or <!-- ... -->
|
||||||
// current pointer: ^ ^ ^
|
// current pointer: ^ ^ ^
|
||||||
|
|
||||||
if( *xml == chXMLTagPre || *xml == chXMLQuestion || *xml == chXMLDash )
|
if( iOffset < xml.size() && (xml[iOffset] == chXMLTagPre || xml[iOffset] == chXMLQuestion || xml[iOffset] == chXMLDash) )
|
||||||
{
|
{
|
||||||
xml++;
|
iOffset++;
|
||||||
|
|
||||||
// skip over 2nd dash
|
// skip over 2nd dash
|
||||||
if( *xml == chXMLDash )
|
if( iOffset < xml.size() && xml[iOffset] == chXMLDash )
|
||||||
xml++;
|
iOffset++;
|
||||||
|
|
||||||
if( *xml != chXMLTagClose )
|
if( iOffset == xml.size() || xml[iOffset] != chXMLTagClose )
|
||||||
{
|
{
|
||||||
// error: <TAG ... / >
|
// error: <TAG ... / >
|
||||||
if( !pi->error_occur )
|
if( !pi->error_occur )
|
||||||
@@ -270,19 +269,19 @@ const char* XNode::Load( const char* xml, PARSEINFO *pi /*= &piDefault*/ )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ill-formed tag
|
// ill-formed tag
|
||||||
return NULL;
|
return string.npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// well-formed tag
|
// well-formed tag
|
||||||
++xml;
|
++iOffset;
|
||||||
|
|
||||||
// UGLY: We want to ignore all XML meta tags. So, since the Node we
|
// UGLY: We want to ignore all XML meta tags. So, since the Node we
|
||||||
// just loaded is a meta tag, then Load ourself again using the rest
|
// just loaded is a meta tag, then Load ourself again using the rest
|
||||||
// of the file until we reach a non-meta tag.
|
// of the file until we reach a non-meta tag.
|
||||||
if( !m_sName.empty() && (m_sName[0] == chXMLQuestion || m_sName[0] == chXMLExclamation) )
|
if( !m_sName.empty() && (m_sName[0] == chXMLQuestion || m_sName[0] == chXMLExclamation) )
|
||||||
xml = Load( xml, pi );
|
iOffset = Load( xml, pi, iOffset );
|
||||||
|
|
||||||
return xml;
|
return iOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// open/close tag <TAG ..> ... </TAG>
|
// open/close tag <TAG ..> ... </TAG>
|
||||||
@@ -290,8 +289,9 @@ const char* XNode::Load( const char* xml, PARSEINFO *pi /*= &piDefault*/ )
|
|||||||
if( XIsEmptyString( m_sValue ) )
|
if( XIsEmptyString( m_sValue ) )
|
||||||
{
|
{
|
||||||
// Text Value
|
// Text Value
|
||||||
const char* pEnd = strchr( ++xml, chXMLTagOpen );
|
++iOffset;
|
||||||
if( pEnd == NULL )
|
unsigned iEnd = xml.find( chXMLTagOpen, iOffset );
|
||||||
|
if( iEnd == string.npos )
|
||||||
{
|
{
|
||||||
if( !pi->error_occur )
|
if( !pi->error_occur )
|
||||||
{
|
{
|
||||||
@@ -301,24 +301,24 @@ const char* XNode::Load( const char* xml, PARSEINFO *pi /*= &piDefault*/ )
|
|||||||
pi->error_string = ssprintf( "%s must be closed with </%s>", m_sName.c_str(), m_sName.c_str() );
|
pi->error_string = ssprintf( "%s must be closed with </%s>", m_sName.c_str(), m_sName.c_str() );
|
||||||
}
|
}
|
||||||
// error cos not exist CloseTag </TAG>
|
// error cos not exist CloseTag </TAG>
|
||||||
return NULL;
|
return string.npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool trim = pi->trim_value;
|
bool trim = pi->trim_value;
|
||||||
SetString( xml, pEnd, &m_sValue, trim );
|
SetString( xml, iOffset, iEnd, &m_sValue, trim );
|
||||||
|
|
||||||
xml = pEnd;
|
iOffset = iEnd;
|
||||||
// TEXTVALUE reference
|
// TEXTVALUE reference
|
||||||
if( pi->entity_value )
|
if( pi->entity_value )
|
||||||
ReplaceEntityText( m_sValue, g_mapEntitiesToChars );
|
ReplaceEntityText( m_sValue, g_mapEntitiesToChars );
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate child nodes
|
// generate child nodes
|
||||||
while( xml && *xml )
|
while( iOffset < xml.size() )
|
||||||
{
|
{
|
||||||
XNode *node = new XNode;
|
XNode *node = new XNode;
|
||||||
|
|
||||||
xml = node->Load( xml,pi );
|
iOffset = node->Load( xml, pi, iOffset );
|
||||||
if( !node->m_sName.empty() )
|
if( !node->m_sName.empty() )
|
||||||
{
|
{
|
||||||
DEBUG_ASSERT( node->m_sName.size() );
|
DEBUG_ASSERT( node->m_sName.size() );
|
||||||
@@ -332,17 +332,17 @@ const char* XNode::Load( const char* xml, PARSEINFO *pi /*= &piDefault*/ )
|
|||||||
// open/close tag <TAG ..> ... </TAG>
|
// open/close tag <TAG ..> ... </TAG>
|
||||||
// ^- current pointer
|
// ^- current pointer
|
||||||
// CloseTag case
|
// CloseTag case
|
||||||
if( xml && xml[0] == chXMLTagOpen && xml[1] == chXMLTagPre )
|
if( iOffset+1 < xml.size() && xml[iOffset] == chXMLTagOpen && xml[iOffset+1] == chXMLTagPre )
|
||||||
{
|
{
|
||||||
// </Close>
|
// </Close>
|
||||||
xml+=2; // C
|
iOffset += 2; // C
|
||||||
|
|
||||||
xml = tcsskip( xml );
|
tcsskip( xml, iOffset );
|
||||||
if( xml == NULL )
|
if( iOffset >= xml.size() )
|
||||||
return NULL;
|
continue;
|
||||||
|
|
||||||
const char* pEnd = strpbrk( xml, " >" );
|
unsigned iEnd = xml.find_first_of( " >", iOffset );
|
||||||
if( pEnd == NULL )
|
if( iEnd == string.npos )
|
||||||
{
|
{
|
||||||
if( !pi->error_occur )
|
if( !pi->error_occur )
|
||||||
{
|
{
|
||||||
@@ -352,17 +352,17 @@ const char* XNode::Load( const char* xml, PARSEINFO *pi /*= &piDefault*/ )
|
|||||||
pi->error_string = ssprintf( "it must be closed with </%s>", m_sName.c_str() );
|
pi->error_string = ssprintf( "it must be closed with </%s>", m_sName.c_str() );
|
||||||
}
|
}
|
||||||
// error
|
// error
|
||||||
return NULL;
|
return string.npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
CString closename;
|
CString closename;
|
||||||
SetString( xml, pEnd, &closename );
|
SetString( xml, iOffset, iEnd, &closename );
|
||||||
xml = pEnd+1;
|
iOffset = iEnd+1;
|
||||||
if( closename == this->m_sName )
|
if( closename == this->m_sName )
|
||||||
{
|
{
|
||||||
// wel-formed open/close
|
// wel-formed open/close
|
||||||
// return '>' or ' ' after pointer
|
// return '>' or ' ' after pointer
|
||||||
return xml;
|
return iOffset;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -374,16 +374,16 @@ const char* XNode::Load( const char* xml, PARSEINFO *pi /*= &piDefault*/ )
|
|||||||
pi->error_code = PIE_NOT_NESTED;
|
pi->error_code = PIE_NOT_NESTED;
|
||||||
pi->error_string = ssprintf( "'<%s> ... </%s>' is not well-formed.", m_sName.c_str(), closename.c_str() );
|
pi->error_string = ssprintf( "'<%s> ... </%s>' is not well-formed.", m_sName.c_str(), closename.c_str() );
|
||||||
}
|
}
|
||||||
return NULL;
|
return string.npos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // Alone child Tag Loaded
|
else // Alone child Tag Loaded
|
||||||
{
|
{
|
||||||
if( xml && XIsEmptyString( m_sValue ) && *xml !=chXMLTagOpen )
|
if( XIsEmptyString( m_sValue ) && iOffset < xml.size() && xml[iOffset] != chXMLTagOpen )
|
||||||
{
|
{
|
||||||
// Text Value
|
// Text Value
|
||||||
const char* pEnd = strchr( xml, chXMLTagOpen );
|
unsigned iEnd = xml.find( chXMLTagOpen, iOffset );
|
||||||
if( pEnd == NULL )
|
if( iEnd == string.npos )
|
||||||
{
|
{
|
||||||
// error cos not exist CloseTag </TAG>
|
// error cos not exist CloseTag </TAG>
|
||||||
if( !pi->error_occur )
|
if( !pi->error_occur )
|
||||||
@@ -393,13 +393,13 @@ const char* XNode::Load( const char* xml, PARSEINFO *pi /*= &piDefault*/ )
|
|||||||
pi->error_code = PIE_NOT_CLOSED;
|
pi->error_code = PIE_NOT_CLOSED;
|
||||||
pi->error_string = ssprintf( "it must be closed with </%s>", m_sName.c_str() );
|
pi->error_string = ssprintf( "it must be closed with </%s>", m_sName.c_str() );
|
||||||
}
|
}
|
||||||
return NULL;
|
return string.npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool trim = pi->trim_value;
|
bool trim = pi->trim_value;
|
||||||
SetString( xml, pEnd, &m_sValue, trim );
|
SetString( xml, iOffset, iEnd, &m_sValue, trim );
|
||||||
|
|
||||||
xml = pEnd;
|
iOffset = iEnd;
|
||||||
//TEXTVALUE
|
//TEXTVALUE
|
||||||
if( pi->entity_value )
|
if( pi->entity_value )
|
||||||
ReplaceEntityText( m_sValue, g_mapEntitiesToChars );
|
ReplaceEntityText( m_sValue, g_mapEntitiesToChars );
|
||||||
@@ -407,7 +407,7 @@ const char* XNode::Load( const char* xml, PARSEINFO *pi /*= &piDefault*/ )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return xml;
|
return iOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Desc : convert plain xml text from parsed xml attirbute
|
// Desc : convert plain xml text from parsed xml attirbute
|
||||||
|
|||||||
@@ -137,8 +137,8 @@ struct XNode
|
|||||||
void SetValue( const DateTime &v );
|
void SetValue( const DateTime &v );
|
||||||
|
|
||||||
// Load/Save XML
|
// Load/Save XML
|
||||||
const char *Load( const char* pszXml, PARSEINFO *pi );
|
unsigned Load( const CString &sXml, PARSEINFO *pi, unsigned iOffset = 0 );
|
||||||
const char *LoadAttributes( const char* pszAttrs, PARSEINFO *pi );
|
unsigned LoadAttributes( const CString &sAttrs, PARSEINFO *pi, unsigned iOffset );
|
||||||
bool GetXML( RageFileBasic &f, DISP_OPT *opt ) const;
|
bool GetXML( RageFileBasic &f, DISP_OPT *opt ) const;
|
||||||
CString GetXML() const;
|
CString GetXML() const;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user