/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library 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 * OpenSceneGraph Public License for more details. */ #include #include #include using namespace osgDB; XmlNode* osgDB::readXmlFile(const std::string& filename,const Options* options) { std::string foundFile = osgDB::findDataFile(filename, options); if (!foundFile.empty()) { XmlNode::Input input; input.open(foundFile); input.readAllDataIntoBuffer(); if (!input) { OSG_NOTICE<<"Could not open XML file: "< root = new XmlNode; root->read(input); return root.release(); } else { OSG_NOTICE<<"Could not find XML file: "< root = new XmlNode; root->read(input); return root.release(); } XmlNode::ControlMap::ControlMap() { setUpControlMappings(); } void XmlNode::ControlMap::addControlToCharacter(const std::string& control, int c) { _controlToCharacterMap[control] = c; _characterToControlMap[c] = control; } void XmlNode::ControlMap::setUpControlMappings() { addControlToCharacter("&",'&'); addControlToCharacter("<",'<'); addControlToCharacter(">",'>'); addControlToCharacter(""",'"'); addControlToCharacter("'",'\''); } XmlNode::Input::Input(): _currentPos(0) { } XmlNode::Input::Input(const Input&): ControlMap(), _currentPos(0) { } XmlNode::Input::~Input() { } void XmlNode::Input::open(const std::string& filename) { _fin.open(filename.c_str()); } void XmlNode::Input::attach(std::istream& fin) { std::ios &fios = _fin; fios.rdbuf(fin.rdbuf()); } void XmlNode::Input::readAllDataIntoBuffer() { while(_fin) { int c = _fin.get(); if (c>=0 && c<=255) { _buffer.push_back(c); } } } void XmlNode::Input::skipWhiteSpace() { while(_currentPos<_buffer.size() && (_buffer[_currentPos]==' ' || _buffer[_currentPos]=='\t' || _buffer[_currentPos]=='\n' || _buffer[_currentPos]=='\r')) { //OSG_NOTICE<<"_currentPos="<<_currentPos<<"_buffer.size()="<<_buffer.size()<<" v="<type = XmlNode::COMMENT; children.push_back(commentNode); input += 4; XmlNode::Input::size_type end = input.find("-->"); commentNode->contents = input.substr(0, end); if (end!=std::string::npos) { OSG_INFO<<"Valid Comment record ["<contents<<"]"<contents<<"]"<"); std::string comment = input.substr(0, end); if (end!=std::string::npos) { OSG_INFO<<"Valid end tag ["<type = XmlNode::INFORMATION; children.push_back(commentNode); ++input; XmlNode::Input::size_type end = input.find(">"); commentNode->contents = input.substr(0, end); if (end!=std::string::npos) { OSG_INFO<<"Valid infomation record ["<contents<<"]"<contents<<"]"<type = XmlNode::INFORMATION; children.push_back(commentNode); input += 9; XmlNode::Input::size_type end = input.find("]]>"); commentNode->contents = input.substr(0, end); if (end!=std::string::npos) { OSG_INFO<<"Valid infomation record ["<contents<<"]"<contents<<"]"<type = XmlNode::INFORMATION; children.push_back(commentNode); input += 2; XmlNode::Input::size_type end = input.find("?>"); commentNode->contents = input.substr(0, end); if (end!=std::string::npos) { OSG_INFO<<"Valid infomation record ["<contents<<"]"<contents<<"]"<type = XmlNode::NODE; children.push_back(childNode); input += 1; input.skipWhiteSpace(); int c = 0; while ((c=input[0])>=0 && c!=' ' && c!='\n' && c!='\r' && c!='>' && c!='/') { childNode->name.push_back(c); ++input; } while ((c=input[0])>=0 && c!='>' && c!='/') { Input::size_type prev_pos = input.currentPosition(); input.skipWhiteSpace(); std::string option; std::string value; if (input[0]=='"') { option.push_back(input[0]); ++input; while((c=input[0])>=0 && c!='"') { if (c=='&') readAndReplaceControl(option, input); else { option.push_back(c); ++input; } } option.push_back(input[0]); ++input; } else { while((c=input[0])>=0 && c!='>' && c!='/' && c!='"' && c!='\'' && c!='=' && c!=' ' && c!='\n' && c!='\r') { option.push_back(c); ++input; } } input.skipWhiteSpace(); if (input[0]=='=') { ++input; input.skipWhiteSpace(); if (input[0]=='"') { ++input; while((c=input[0])>=0 && c!='"') { if (c=='&') readAndReplaceControl(value, input); else { value.push_back(c); ++input; } } ++input; } else if (input[0]=='\'') { ++input; while((c=input[0])>=0 && c!='\'') { if (c=='&') readAndReplaceControl(value, input); else { value.push_back(c); ++input; } } ++input; } else { ++input; while((c=input[0])>=0 && c!=' ' && c!='\n' && c!='\r' && c!='"' && c!='\'' && c!='>') { value.push_back(c); ++input; } } } if (prev_pos == input.currentPosition()) { OSG_NOTICE<<"Error, parser iterator not advanced, position: "<properties[option] = value; } } if ((c=input[0])>=0 && (c=='>' || c=='/')) { ++input; OSG_INFO<<"Valid tag ["<name<<"]"<=0 && c=='>') { ++input; OSG_INFO<<"tag is closed correctly"<type = ATOM; } else OSG_NOTICE<<"Error: tag is not closed correctly"<read(input); if (!result) return false; } if (type==NODE && !children.empty()) type = GROUP; } else { OSG_NOTICE<<"Unclosed tag ["<name<<"]"<"<"; writeString(controlMap, fout, contents); fout<<""<"<"<"<"<second; else fout.put(c); } return true; } bool XmlNode::writeChildren(const ControlMap& /*controlMap*/, std::ostream& fout, const std::string& indent) const { for(Children::const_iterator citr = children.begin(); citr != children.end(); ++citr) { if (!(*citr)->write(fout, indent)) return false; } return true; } bool XmlNode::writeProperties(const ControlMap& controlMap, std::ostream& fout) const { for(Properties::const_iterator oitr = properties.begin(); oitr != properties.end(); ++oitr) { fout<<" "<first<<"=\""; if (!writeString(controlMap,fout,oitr->second)) return false; 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 "<