From ab1920c4279ec75e91585ccac3612cec9303e645 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 30 Sep 2010 09:34:41 +0000 Subject: [PATCH] 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." --- include/osgDB/XmlParser | 2 + src/osgDB/XmlParser.cpp | 54 ++++++++----- src/osgPlugins/osg/XmlStreamOperator.h | 101 ++++++++++++++++--------- 3 files changed, 103 insertions(+), 54 deletions(-) diff --git a/include/osgDB/XmlParser b/include/osgDB/XmlParser index 012127ff3..23bd68a46 100644 --- a/include/osgDB/XmlParser +++ b/include/osgDB/XmlParser @@ -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); }; } diff --git a/src/osgDB/XmlParser.cpp b/src/osgDB/XmlParser.cpp index 57c466a86..9513ae976 100644 --- a/src/osgDB/XmlParser.cpp +++ b/src/osgDB/XmlParser.cpp @@ -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 "<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()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(); }