1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#ifndef OSGDB_XML_PARSER
15#define OSGDB_XML_PARSER 1
16
17#include <osgDB/Registry>
18
19namespace osgDB {
20
21// forward declare
22class XmlNode;
23
24/** read an Xml file, find the file in Options DataFilePathList.*/
25extern OSGDB_EXPORT XmlNode* readXmlFile(const std::string& filename,const Options* options);
26
27/** read an Xml file, find the file in osgDB::Registry's eaderWriter::Options DataFilePathList.*/
28inline XmlNode* readXmlFile(const std::string& filename)
29{
30    return readXmlFile(filename, osgDB::Registry::instance()->getOptions());
31}
32
33/** read an Xml from from an istream.*/
34extern OSGDB_EXPORT XmlNode* readXmlStream(std::istream& fin);
35
36extern OSGDB_EXPORT std::string trimEnclosingSpaces(const std::string& str);
37
38/** XmlNode class for very basic reading and writing of xml files.*/
39class OSGDB_EXPORT XmlNode : public osg::Referenced
40{
41    public:
42
43        XmlNode();
44
45        enum NodeType
46        {
47            UNASSIGNED,
48            ATOM,
49            NODE,
50            GROUP,
51            ROOT,
52            COMMENT,
53            INFORMATION
54        };
55
56        typedef std::map< std::string, std::string > Properties;
57        typedef std::vector< osg::ref_ptr<XmlNode> >  Children;
58
59        NodeType        type;
60        std::string     name;
61        std::string     contents;
62        Properties      properties;
63        Children        children;
64
65        std::string getTrimmedContents() const { return trimEnclosingSpaces(contents); }
66
67    public:
68
69        class OSGDB_EXPORT ControlMap
70        {
71            public:
72                ControlMap();
73
74                typedef std::map< std::string, int > ControlToCharacterMap;
75                typedef std::map< int, std::string> CharacterToControlMap;
76
77                void addControlToCharacter(const std::string& control, int c);
78
79                ControlToCharacterMap _controlToCharacterMap;
80                CharacterToControlMap _characterToControlMap;
81
82            private:
83
84                void setUpControlMappings();
85
86        };
87
88        class OSGDB_EXPORT Input : public ControlMap
89        {
90            public:
91
92                Input();
93                Input(const Input&);
94
95                ~Input();
96
97                typedef std::string::size_type size_type;
98
99                void open(const std::string& filename);
100                void attach(std::istream& istream);
101
102                void readAllDataIntoBuffer();
103
104                operator bool () const { return _currentPos<_buffer.size(); }
105
106                size_type currentPosition() const { return _currentPos; }
107
108                int get() { if (_currentPos<_buffer.size()) return _buffer[_currentPos++]; else return -1; }
109
110                int operator [] (size_type i) const { if ((_currentPos+i)<_buffer.size()) return _buffer[_currentPos+i]; else return -1; }
111
112                void operator ++ () { if (_currentPos<_buffer.size()) ++_currentPos; }
113
114                void operator += (size_type n) { if ((_currentPos+n)<_buffer.size()) _currentPos+=n; else _currentPos = _buffer.size(); }
115
116                void skipWhiteSpace();
117
118                std::string substr(size_type pos, size_type n=std::string::npos) { return (_currentPos<_buffer.size()) ? _buffer.substr(_currentPos+pos,n) : std::string(); }
119
120                size_type find(const std::string& str)
121                {
122                    if (_currentPos<_buffer.size())
123                    {
124                        size_type pos = _buffer.find(str, _currentPos);
125                        if (pos==std::string::npos) return std::string::npos;
126                        else return pos-_currentPos;
127                    } else return std::string::npos;
128                }
129
130                bool match(const std::string& str) { return (_currentPos<_buffer.size()) ? _buffer.compare(_currentPos, str.size(), str)==0 : false; }
131
132            private:
133
134                size_type _currentPos;
135
136                std::ifstream _fin;
137                std::string  _buffer;
138
139        };
140
141        bool read(Input& input);
142        bool write(std::ostream& fout, const std::string& indent = "") const;
143
144        bool write(const ControlMap& controlMap, std::ostream& fout, const std::string& indent = "") const;
145        bool writeString(const ControlMap& controlMap, std::ostream& fout, const std::string& str) const;
146
147    protected:
148
149        bool writeChildren(const ControlMap& controlMap, std::ostream& fout, const std::string& indent) const;
150        bool writeProperties(const ControlMap& controlMap, std::ostream& fout) const;
151
152        bool readAndReplaceControl(std::string& contents, Input& input);
153};
154
155}
156#endif
157