~ubuntu-branches/debian/experimental/openscenegraph/experimental

« back to all changes in this revision

Viewing changes to OpenSceneGraph/src/osgPlugins/osg/XmlStreamOperator.h

  • Committer: Bazaar Package Importer
  • Author(s): Alberto Luaces
  • Date: 2011-01-29 11:36:29 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20110129113629-qisrm2kdqlurc7t3
Tags: 2.9.11-1
* Removed bug-555869-ftbfs_with_binutils_gold.dpatch since upstream has
  already taken care of the issue.
* Removed bug-528229.dpatch since the pkgconfig files are now also split
  in upstream.
* Removed explicit dependency on GLU.
* Upstream no longer includes osgIntrospection (Closes: #592420).
* Disabled zip plugin as its implementation stores an embedded copy of
  zlib.
* Enabled Qt support. Thanks James Goppert.
* Enabled SVG and PDF plugins. Thanks James Goppert.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifndef OSGDB_XMLSTREAMOPERATOR
 
2
#define OSGDB_XMLSTREAMOPERATOR
 
3
 
 
4
#include <osgDB/StreamOperator>
 
5
#include <osgDB/XmlParser>
 
6
#include <sstream>
 
7
 
 
8
class XmlOutputIterator : public osgDB::OutputIterator
 
9
{
 
10
public:
 
11
    enum ReadLineType
 
12
    {
 
13
        FIRST_LINE=0,        // The first line of file
 
14
        NEW_LINE,            // A new line without checking its type
 
15
        PROP_LINE,           // A line starting with osgDB::PROPERTY
 
16
        SUB_PROP_LINE,       // A property line containing another osgDB::PROPERTY
 
17
        BEGIN_BRACKET_LINE,  // A line ending with a '{'
 
18
        END_BRACKET_LINE,    // A line starting with a '}'
 
19
        TEXT_LINE            // A text line, e.g. recording array elements
 
20
    };
 
21
    
 
22
    XmlOutputIterator( std::ostream* ostream )
 
23
    :   _readLineType(FIRST_LINE), _prevReadLineType(FIRST_LINE), _hasSubProperty(false)
 
24
    {
 
25
        _out = ostream;
 
26
        _root = new osgDB::XmlNode;
 
27
        _root->type = osgDB::XmlNode::GROUP;
 
28
    }
 
29
    
 
30
    virtual ~XmlOutputIterator() {}
 
31
    
 
32
    virtual bool isBinary() const { return false; }
 
33
    
 
34
    virtual void writeBool( bool b )
 
35
    { addToCurrentNode( b ? std::string("TRUE") : std::string("FALSE") ); }
 
36
    
 
37
    virtual void writeChar( char c )
 
38
    { _sstream << (short)c; addToCurrentNode( _sstream.str() ); _sstream.str(""); }
 
39
    
 
40
    virtual void writeUChar( unsigned char c )
 
41
    { _sstream << (unsigned short)c; addToCurrentNode( _sstream.str() ); _sstream.str(""); }
 
42
    
 
43
    virtual void writeShort( short s )
 
44
    { _sstream << s; addToCurrentNode( _sstream.str() ); _sstream.str(""); }
 
45
    
 
46
    virtual void writeUShort( unsigned short s )
 
47
    { _sstream << s; addToCurrentNode( _sstream.str() ); _sstream.str(""); }
 
48
    
 
49
    virtual void writeInt( int i )
 
50
    { _sstream << i; addToCurrentNode( _sstream.str() ); _sstream.str(""); }
 
51
    
 
52
    virtual void writeUInt( unsigned int i )
 
53
    { _sstream << i; addToCurrentNode( _sstream.str() ); _sstream.str(""); }
 
54
    
 
55
    virtual void writeLong( long l )
 
56
    { _sstream << l; addToCurrentNode( _sstream.str() ); _sstream.str(""); }
 
57
    
 
58
    virtual void writeULong( unsigned long l )
 
59
    { _sstream << l; addToCurrentNode( _sstream.str() ); _sstream.str(""); }
 
60
    
 
61
    virtual void writeFloat( float f )
 
62
    { _sstream << f; addToCurrentNode( _sstream.str() ); _sstream.str(""); }
 
63
    
 
64
    virtual void writeDouble( double d )
 
65
    { _sstream << d; addToCurrentNode( _sstream.str() ); _sstream.str(""); }
 
66
    
 
67
    virtual void writeString( const std::string& s )
 
68
    { addToCurrentNode( s, true ); }
 
69
 
 
70
    virtual void writeStream( std::ostream& (*fn)(std::ostream&) )
 
71
    {
 
72
        if ( isEndl( fn ) )
 
73
        {
 
74
            if ( _readLineType==PROP_LINE || _readLineType==END_BRACKET_LINE )
 
75
            {
 
76
                if ( _hasSubProperty )
 
77
                {
 
78
                    _hasSubProperty = false;
 
79
                    popNode();  // Exit the sub-property element
 
80
                }
 
81
                popNode();  // Exit the property element
 
82
            }
 
83
            else if ( _readLineType==SUB_PROP_LINE )
 
84
            {
 
85
                _hasSubProperty = false;
 
86
                popNode();  // Exit the sub-property element
 
87
                popNode();  // Exit the property element
 
88
            }
 
89
            else if ( _readLineType==TEXT_LINE )
 
90
                addToCurrentNode( fn );
 
91
            
 
92
            setLineType( NEW_LINE );
 
93
        }
 
94
        else
 
95
            addToCurrentNode( fn );
 
96
    }
 
97
    
 
98
    virtual void writeBase( std::ios_base& (*fn)(std::ios_base&) )
 
99
    {
 
100
        _sstream << fn;
 
101
    }
 
102
    
 
103
    virtual void writeGLenum( const osgDB::ObjectGLenum& value )
 
104
    {
 
105
        GLenum e = value.get(); 
 
106
        const std::string& enumString = osgDB::Registry::instance()->getObjectWrapperManager()->getString("GL", e);
 
107
        addToCurrentNode( enumString, true );
 
108
    }
 
109
    
 
110
    virtual void writeProperty( const osgDB::ObjectProperty& prop )
 
111
    {
 
112
        std::string enumString = prop._name;
 
113
        if ( prop._mapProperty )
 
114
        {
 
115
            enumString = osgDB::Registry::instance()->getObjectWrapperManager()->getString(prop._name, prop._value);
 
116
            addToCurrentNode( enumString, true );
 
117
        }
 
118
        else
 
119
        {
 
120
            if ( _readLineType==NEW_LINE || _readLineType==BEGIN_BRACKET_LINE )
 
121
            {
 
122
                pushNode( enumString );
 
123
                setLineType( PROP_LINE );
 
124
            }
 
125
            else if ( _readLineType==PROP_LINE )
 
126
            {
 
127
                pushNode( enumString );
 
128
                setLineType( SUB_PROP_LINE );
 
129
                _hasSubProperty = true;
 
130
            }
 
131
            else if ( _readLineType==SUB_PROP_LINE )
 
132
            {
 
133
                popNode();
 
134
                pushNode( enumString );
 
135
            }
 
136
        }
 
137
    }
 
138
    
 
139
    virtual void writeMark( const osgDB::ObjectMark& mark )
 
140
    {
 
141
        int delta = mark._indentDelta;
 
142
        if ( delta>0 )
 
143
        {
 
144
            setLineType( BEGIN_BRACKET_LINE );
 
145
        }
 
146
        else if ( delta<0 )
 
147
        {
 
148
            setLineType( END_BRACKET_LINE );
 
149
        }
 
150
    }
 
151
    
 
152
    virtual void writeCharArray( const char* s, unsigned int size ) {}
 
153
    
 
154
    virtual void writeWrappedString( const std::string& str )
 
155
    {
 
156
        std::string realStr;
 
157
        for ( std::string::const_iterator itr=str.begin(); itr!=str.end(); ++itr )
 
158
        {
 
159
            char ch = *itr;
 
160
            if ( ch=='\"' ) realStr += '\\';
 
161
            else if ( ch=='\\' ) realStr += '\\';
 
162
            realStr += ch;
 
163
        }
 
164
        realStr.insert( std::string::size_type(0), 1, '\"' );
 
165
        realStr += '\"';
 
166
        addToCurrentNode( realStr );
 
167
    }
 
168
    
 
169
    virtual void flush()
 
170
    {
 
171
        osg::ref_ptr<osgDB::XmlNode> xmlRoot = new osgDB::XmlNode;
 
172
        xmlRoot->type = osgDB::XmlNode::ROOT;
 
173
        xmlRoot->children.push_back( _root.get() );
 
174
        xmlRoot->write( *_out );
 
175
    }
 
176
    
 
177
protected:
 
178
    void addToCurrentNode( const std::string& str, bool isString=false )
 
179
    {
 
180
        if ( _readLineType==FIRST_LINE )
 
181
        {
 
182
            _root->name = str;
 
183
            return;
 
184
        }
 
185
        
 
186
        if ( _readLineType==NEW_LINE )
 
187
        {
 
188
            if ( isString )
 
189
            {
 
190
                pushNode( str );
 
191
                setLineType( PROP_LINE );
 
192
                return;
 
193
            }
 
194
            else
 
195
                setLineType( TEXT_LINE );
 
196
        }
 
197
        
 
198
        if ( _readLineType==TEXT_LINE )
 
199
        {
 
200
            std::string& text = _nodePath.back()->properties["text"];
 
201
            text += str + ' ';
 
202
        }
 
203
        else if ( _nodePath.size()>0 )
 
204
        {
 
205
            std::string& prop = _nodePath.back()->properties["attribute"];
 
206
            if ( !prop.empty() ) prop += ' ';
 
207
            prop += str;
 
208
        }
 
209
        else
 
210
        {
 
211
            pushNode( str );
 
212
            setLineType( PROP_LINE );
 
213
        }
 
214
    }
 
215
    
 
216
    void addToCurrentNode( std::ostream& (*fn)(std::ostream&) )
 
217
    {
 
218
        if ( _nodePath.size()>0 )
 
219
        {
 
220
            osgDB::XmlNode* node = _nodePath.back();
 
221
            _sstream << fn;
 
222
            if ( _readLineType==TEXT_LINE ) node->properties["text"] += _sstream.str();
 
223
            else node->properties["attribute"] += _sstream.str();
 
224
            _sstream.str("");
 
225
        }
 
226
    }
 
227
    
 
228
    osgDB::XmlNode* pushNode( const std::string& name )
 
229
    {
 
230
        osg::ref_ptr<osgDB::XmlNode> node = new osgDB::XmlNode;
 
231
        node->type = osgDB::XmlNode::ATOM;
 
232
        
 
233
        // Set element name without '#' and '::' characters
 
234
        std::string realName;
 
235
        if ( name.length()>0 && name[0]=='#' )
 
236
            realName = name.substr(1);
 
237
        else
 
238
        {
 
239
            realName = name;
 
240
            
 
241
            std::string::size_type pos = realName.find("::");
 
242
            if ( pos!=std::string::npos )
 
243
                realName.replace( pos, 2, "--" );
 
244
        }
 
245
        node->name = realName;
 
246
        
 
247
        if ( _nodePath.size()>0 )
 
248
        {
 
249
            _nodePath.back()->type = osgDB::XmlNode::GROUP;
 
250
            _nodePath.back()->children.push_back(node);
 
251
        }
 
252
        else
 
253
            _root->children.push_back(node);
 
254
        
 
255
        _nodePath.push_back( node.get() );
 
256
        return node.get();
 
257
    }
 
258
    
 
259
    osgDB::XmlNode* popNode()
 
260
    {
 
261
        osgDB::XmlNode* node = NULL;
 
262
        if ( _nodePath.size()>0 )
 
263
        {
 
264
            node = _nodePath.back();
 
265
            trimEndMarkers( node, "attribute" );
 
266
            trimEndMarkers( node, "text" );
 
267
            _nodePath.pop_back();
 
268
        }
 
269
        return node;
 
270
    }
 
271
    
 
272
    void trimEndMarkers( osgDB::XmlNode* node, const std::string& name )
 
273
    {
 
274
        osgDB::XmlNode::Properties::iterator itr = node->properties.find(name);
 
275
        if ( itr==node->properties.end() ) return;
 
276
        
 
277
        std::string& str = itr->second;
 
278
        if ( !str.empty() )
 
279
        {
 
280
            std::string::size_type end = str.find_last_not_of( " \t\r\n" );
 
281
            if ( end==std::string::npos ) return;
 
282
            str.erase( end+1 );
 
283
        }
 
284
        
 
285
        if ( str.empty() )
 
286
            node->properties.erase(itr);
 
287
    }
 
288
    
 
289
    void setLineType( ReadLineType type )
 
290
    {
 
291
        _prevReadLineType = _readLineType;
 
292
        _readLineType = type;
 
293
    }
 
294
    
 
295
    typedef std::vector<osgDB::XmlNode*> XmlNodePath;
 
296
    XmlNodePath _nodePath;
 
297
    
 
298
    osg::ref_ptr<osgDB::XmlNode> _root;
 
299
    std::stringstream _sstream;
 
300
    
 
301
    ReadLineType _readLineType;
 
302
    ReadLineType _prevReadLineType;
 
303
    bool _hasSubProperty;
 
304
};
 
305
 
 
306
class XmlInputIterator : public osgDB::InputIterator
 
307
{
 
308
public:
 
309
    XmlInputIterator( std::istream* istream )
 
310
    {
 
311
        _in = istream;
 
312
        _root = osgDB::readXmlStream( *istream );
 
313
        
 
314
        if ( _root.valid() && _root->children.size()>0 )
 
315
            _nodePath.push_back( _root->children[0] );
 
316
    }
 
317
    
 
318
    virtual ~XmlInputIterator() {}
 
319
    
 
320
    virtual bool isBinary() const { return false; }
 
321
    
 
322
    virtual void readBool( bool& b )
 
323
    {
 
324
        std::string boolString;
 
325
        if ( prepareStream() ) _sstream >> boolString;
 
326
        if ( boolString=="TRUE" ) b = true;
 
327
        else b = false;
 
328
    }
 
329
    
 
330
    virtual void readChar( char& c )
 
331
    {
 
332
        short s = 0;
 
333
        if ( prepareStream() ) _sstream >> s;
 
334
        c = (char)s;
 
335
    }
 
336
    
 
337
    virtual void readSChar( signed char& c )
 
338
    {
 
339
        short s = 0;
 
340
        if ( prepareStream() ) _sstream >> s;
 
341
        c = (signed char)s;
 
342
    }
 
343
    
 
344
    virtual void readUChar( unsigned char& c )
 
345
    {
 
346
        unsigned short s = 0;
 
347
        if ( prepareStream() ) _sstream >> s;
 
348
        c = (unsigned char)s;
 
349
    }
 
350
    
 
351
    virtual void readShort( short& s )
 
352
    { if ( prepareStream() ) _sstream >> s; }
 
353
    
 
354
    virtual void readUShort( unsigned short& s )
 
355
    { if ( prepareStream() ) _sstream >> s; }
 
356
    
 
357
    virtual void readInt( int& i )
 
358
    { if ( prepareStream() ) _sstream >> i; }
 
359
    
 
360
    virtual void readUInt( unsigned int& i )
 
361
    { if ( prepareStream() ) _sstream >> i; }
 
362
    
 
363
    virtual void readLong( long& l )
 
364
    { if ( prepareStream() ) _sstream >> l; }
 
365
    
 
366
    virtual void readULong( unsigned long& l )
 
367
    { if ( prepareStream() ) _sstream >> l; }
 
368
    
 
369
    virtual void readFloat( float& f )
 
370
    { if ( prepareStream() ) _sstream >> f; }
 
371
    
 
372
    virtual void readDouble( double& d )
 
373
    { if ( prepareStream() ) _sstream >> d; }
 
374
    
 
375
    virtual void readString( std::string& s )
 
376
    {
 
377
        if ( prepareStream() ) _sstream >> s;
 
378
        
 
379
        // Replace '--' to '::' to get correct wrapper class
 
380
        std::string::size_type pos = s.find("--");
 
381
        if ( pos!=std::string::npos )
 
382
            s.replace( pos, 2, "::" );
 
383
    }
 
384
    
 
385
    virtual void readStream( std::istream& (*fn)(std::istream&) )
 
386
    { if ( prepareStream() ) _sstream >> fn; }
 
387
    
 
388
    virtual void readBase( std::ios_base& (*fn)(std::ios_base&) )
 
389
    { _sstream >> fn; }
 
390
    
 
391
    virtual void readGLenum( osgDB::ObjectGLenum& value )
 
392
    {
 
393
        GLenum e = 0;
 
394
        std::string enumString;
 
395
        if ( prepareStream() ) _sstream >> enumString;
 
396
        e = osgDB::Registry::instance()->getObjectWrapperManager()->getValue("GL", enumString);
 
397
        value.set( e );
 
398
    }
 
399
    
 
400
    virtual void readProperty( osgDB::ObjectProperty& prop )
 
401
    {
 
402
        int value = 0;
 
403
        std::string enumString;
 
404
        if ( prepareStream() ) _sstream >> enumString;
 
405
        if ( prop._mapProperty )
 
406
        {
 
407
            value = osgDB::Registry::instance()->getObjectWrapperManager()->getValue(prop._name, enumString);
 
408
        }
 
409
        else
 
410
        {
 
411
            // Replace '--' to '::' to get correct wrapper class
 
412
            std::string::size_type pos = enumString.find("--");
 
413
            if ( pos!=std::string::npos )
 
414
                enumString.replace( pos, 2, "::" );
 
415
            
 
416
            if ( prop._name!=enumString )
 
417
            {
 
418
                if ( prop._name[0]=='#' )
 
419
                    enumString = '#' + enumString;
 
420
                if ( prop._name!=enumString )
 
421
                {
 
422
                    OSG_WARN << "XmlInputIterator::readProperty(): Unmatched property "
 
423
                                           << enumString << ", expecting " << prop._name << std::endl;
 
424
                }
 
425
            }
 
426
            prop._name = enumString;
 
427
        }
 
428
        prop.set( value );
 
429
    }
 
430
    
 
431
    virtual void readMark( osgDB::ObjectMark& mark ) {}
 
432
    
 
433
    virtual void readCharArray( char* s, unsigned int size ) {}
 
434
    
 
435
    virtual void readWrappedString( std::string& str )
 
436
    {
 
437
        if ( !prepareStream() ) return;
 
438
        
 
439
        // Read available string in the stream buffer
 
440
        unsigned int availSize = _sstream.rdbuf()->in_avail();
 
441
        std::string realStr = _sstream.str();
 
442
        _sstream.str("");
 
443
        
 
444
        // Find the first quot or valid character
 
445
        bool hasQuot = false;
 
446
        std::string::iterator itr = realStr.begin() + (realStr.size() - availSize);
 
447
        for ( ; itr!=realStr.end(); ++itr )
 
448
        {
 
449
            char ch = *itr;
 
450
            if ((ch==' ') || (ch=='\n') || (ch=='\r')) continue;
 
451
            else if (ch=='"') hasQuot = true;
 
452
            else str += ch;
 
453
 
 
454
            itr++;
 
455
            break;
 
456
        }
 
457
 
 
458
        for ( ; itr!=realStr.end(); ++itr )
 
459
        {
 
460
            char ch = *itr;
 
461
            if (ch=='\\')
 
462
            {
 
463
                itr++;
 
464
                if (itr == realStr.end()) break;
 
465
                str += *itr;
 
466
            }
 
467
            else if (hasQuot && ch=='"')
 
468
            {
 
469
                // Get to the end of the wrapped string
 
470
                itr++;
 
471
                break;
 
472
            }
 
473
            else
 
474
                str += ch;
 
475
        }
 
476
        if (itr != realStr.end())
 
477
        {
 
478
            _sstream << std::string(itr, realStr.end());
 
479
        }
 
480
    }
 
481
    
 
482
    virtual bool matchString( const std::string& str )
 
483
    {
 
484
        prepareStream();
 
485
        std::string strInStream = osgDB::trimEnclosingSpaces(_sstream.str());
 
486
        if ( strInStream==str )
 
487
        {
 
488
            std::string prop; readString( prop );
 
489
            return true;
 
490
        }
 
491
        return false;
 
492
    }
 
493
    
 
494
    virtual void advanceToCurrentEndBracket() {}
 
495
    
 
496
protected:
 
497
    bool isReadable() const { return _sstream.rdbuf()->in_avail()>0; }
 
498
    
 
499
    bool prepareStream()
 
500
    {
 
501
        if ( !_nodePath.size() ) return false;
 
502
        if ( isReadable() ) return true;
 
503
        _sstream.clear();
 
504
        
 
505
        osgDB::XmlNode* current = _nodePath.back().get();
 
506
        if ( current->type!=osgDB::XmlNode::COMMENT )
 
507
        {
 
508
            if ( !current->name.empty() )
 
509
            {
 
510
                _sstream.str( current->name );
 
511
                current->name.clear();
 
512
                return true;
 
513
            }
 
514
            
 
515
            if ( current->properties.size()>0 )
 
516
            {
 
517
                if ( applyPropertyToStream(current, "attribute") ) return true;
 
518
                else if ( applyPropertyToStream(current, "text") ) return true;
 
519
            }
 
520
            
 
521
            if ( current->children.size()>0 )
 
522
            {
 
523
                _nodePath.push_back( current->children.front() );
 
524
                current->children.erase( current->children.begin() );
 
525
                return prepareStream();
 
526
            }
 
527
        }
 
528
        _nodePath.pop_back();
 
529
        return prepareStream();
 
530
    }
 
531
    
 
532
    bool applyPropertyToStream( osgDB::XmlNode* node, const std::string& name )
 
533
    {
 
534
        osgDB::XmlNode::Properties::iterator itr = node->properties.find(name);
 
535
        if ( itr!=node->properties.end() )
 
536
        {
 
537
            _sstream.str( itr->second );
 
538
            node->properties.erase( itr );
 
539
            return true;
 
540
        }
 
541
        return false;
 
542
    }
 
543
    
 
544
    typedef std::vector< osg::ref_ptr<osgDB::XmlNode> > XmlNodePath;
 
545
    XmlNodePath _nodePath;
 
546
    
 
547
    osg::ref_ptr<osgDB::XmlNode> _root;
 
548
    std::stringstream _sstream;
 
549
};
 
550
 
 
551
#endif