From Wang Rui, "I've fixed the problem that osgx format doesn't read the Font property and wrapped string correctly. The first problem happened because the matchString() made a mistake in comparing two strings with the same start but different size. The second just needs complete rewriting of writeWrappedString() and readWrappedString() in src/osgPlugins/osg/XmlStreamOperator.h

I also fixed a possible bug in osgDB::XmlParser that doesn't handle control characters (like " to ") when reading node attributes, because the writeWrappedString() and readWrappedString() now depend heavily on control characters. An additional improvement is that osgx now supports comments."
This commit is contained in:
Robert Osfield
2010-09-30 09:34:41 +00:00
parent 47af827648
commit ab1920c427
3 changed files with 103 additions and 54 deletions

View File

@@ -148,6 +148,8 @@ class OSGDB_EXPORT XmlNode : public osg::Referenced
bool writeChildren(const ControlMap& controlMap, std::ostream& fout, const std::string& indent) const;
bool writeProperties(const ControlMap& controlMap, std::ostream& fout) const;
bool readAndReplaceControl(std::string& contents, Input& input);
};
}

View File

@@ -258,8 +258,13 @@ bool XmlNode::read(Input& input)
++input;
while((c=input[0])>=0 && c!='"')
{
value.push_back(c);
++input;
if (c=='&')
readAndReplaceControl(value, input);
else
{
value.push_back(c);
++input;
}
}
++input;
}
@@ -268,8 +273,13 @@ bool XmlNode::read(Input& input)
++input;
while((c=input[0])>=0 && c!='\'')
{
value.push_back(c);
++input;
if (c=='&')
readAndReplaceControl(value, input);
else
{
value.push_back(c);
++input;
}
}
++input;
}
@@ -335,20 +345,7 @@ bool XmlNode::read(Input& input)
if (c=='&')
{
std::string value;
while(input && (c=input.get())!=';') { value.push_back(c); }
value.push_back(c);
if (input._controlToCharacterMap.count(value)!=0)
{
c = input._controlToCharacterMap[value];
OSG_INFO<<"Read control character "<<value<<" converted to "<<char(c)<<std::endl;
contents.push_back(c);
}
else
{
OSG_NOTICE<<"Warning: read control character "<<value<<", but have no mapping to convert it to."<<std::endl;
}
readAndReplaceControl(contents, input);
}
else
{
@@ -459,3 +456,24 @@ bool XmlNode::writeProperties(const ControlMap& controlMap, std::ostream& fout)
return true;
}
bool XmlNode::readAndReplaceControl(std::string& contents, XmlNode::Input& input)
{
int c = 0;
std::string value;
while(input && (c=input.get())!=';') { value.push_back(c); }
value.push_back(c);
if (input._controlToCharacterMap.count(value)!=0)
{
c = input._controlToCharacterMap[value];
OSG_INFO<<"Read control character "<<value<<" converted to "<<char(c)<<std::endl;
contents.push_back(c);
return true;
}
else
{
OSG_NOTICE<<"Warning: read control character "<<value<<", but have no mapping to convert it to."<<std::endl;
return false;
}
}

View File

@@ -156,11 +156,13 @@ public:
std::string realStr;
for ( std::string::const_iterator itr=str.begin(); itr!=str.end(); ++itr )
{
if ( *itr=='\"' )
realStr += "''";
else
realStr += *itr;
char ch = *itr;
if ( ch=='\"' ) realStr += '\\';
else if ( ch=='\\' ) realStr += '\\';
realStr += ch;
}
realStr.insert( 0, 1, '\"' );
realStr += '\"';
addToCurrentNode( realStr );
}
@@ -432,31 +434,56 @@ public:
virtual void readWrappedString( std::string& str )
{
std::string realStr;
if ( prepareStream() ) std::getline( _sstream, realStr );
for ( std::string::const_iterator itr=realStr.begin(); itr!=realStr.end(); ++itr )
if ( !prepareStream() ) return;
// Read available string in the stream buffer
unsigned int availSize = _sstream.rdbuf()->in_avail();
std::string realStr = _sstream.str();
_sstream.str("");
// Find the first quot or valid character
bool hasQuot = false;
std::string::iterator itr = realStr.begin() + (realStr.size() - availSize);
for ( ; itr!=realStr.end(); ++itr )
{
if ( *itr=='\'' )
char ch = *itr;
if ((ch==' ') || (ch=='\n') || (ch=='\r')) continue;
else if (ch=='"') hasQuot = true;
else str += ch;
itr++;
break;
}
for ( ; itr!=realStr.end(); ++itr )
{
char ch = *itr;
if (ch=='\\')
{
itr++;
if ( itr==realStr.end() ) break;
if ( *itr=='\'' ) str += '\"';
else str += '\'' + *itr;
if (itr == realStr.end()) break;
str += *itr;
}
else if (hasQuot && ch=='"')
{
// Get to the end of the wrapped string
itr++;
break;
}
else
str += *itr;
str += ch;
}
if (itr != realStr.end())
{
_sstream << std::string(itr, realStr.end());
}
}
virtual bool matchString( const std::string& str )
{
prepareStream();
unsigned int size = str.length();
if ( _sstream.str().length()<size ) return false;
int result = _sstream.str().compare( 0, size, str );
if ( !result )
std::string strInStream = osgDB::trimEnclosingSpaces(_sstream.str());
if ( strInStream==str )
{
std::string prop; readString( prop );
return true;
@@ -476,26 +503,28 @@ protected:
_sstream.clear();
osgDB::XmlNode* current = _nodePath.back().get();
if ( !current->name.empty() )
if ( current->type!=osgDB::XmlNode::COMMENT )
{
_sstream.str( current->name );
current->name.clear();
return true;
if ( !current->name.empty() )
{
_sstream.str( current->name );
current->name.clear();
return true;
}
if ( current->properties.size()>0 )
{
if ( applyPropertyToStream(current, "attribute") ) return true;
else if ( applyPropertyToStream(current, "text") ) return true;
}
if ( current->children.size()>0 )
{
_nodePath.push_back( current->children.front() );
current->children.erase( current->children.begin() );
return prepareStream();
}
}
if ( current->properties.size()>0 )
{
if ( applyPropertyToStream(current, "attribute") ) return true;
else if ( applyPropertyToStream(current, "text") ) return true;
}
if ( current->children.size()>0 )
{
_nodePath.push_back( current->children.front() );
current->children.erase( current->children.begin() );
return prepareStream();
}
_nodePath.pop_back();
return prepareStream();
}