1 #ifndef OSG2_BINARYSTREAMOPERATOR
2 #define OSG2_BINARYSTREAMOPERATOR
3 
4 #include <osgDB/StreamOperator>
5 #include <osg/Types>
6 #include <vector>
7 
8 
9 class BinaryOutputIterator : public osgDB::OutputIterator
10 {
11 public:
BinaryOutputIterator(std::ostream * ostream)12     BinaryOutputIterator( std::ostream* ostream ) { _out = ostream; }
~BinaryOutputIterator()13     virtual ~BinaryOutputIterator() {}
14 
isBinary()15     virtual bool isBinary() const { return true; }
16 
writeBool(bool b)17     virtual void writeBool( bool b )
18     { char c = b?1:0; _out->write( &c, osgDB::CHAR_SIZE ); }
19 
writeChar(char c)20     virtual void writeChar( char c )
21     { _out->write( &c, osgDB::CHAR_SIZE ); }
22 
writeUChar(unsigned char c)23     virtual void writeUChar( unsigned char c )
24     { _out->write( (char*)&c, osgDB::CHAR_SIZE ); }
25 
writeShort(short s)26     virtual void writeShort( short s )
27     { _out->write( (char*)&s, osgDB::SHORT_SIZE ); }
28 
writeUShort(unsigned short s)29     virtual void writeUShort( unsigned short s )
30     { _out->write( (char*)&s, osgDB::SHORT_SIZE ); }
31 
writeInt(int i)32     virtual void writeInt( int i )
33     { _out->write( (char*)&i, osgDB::INT_SIZE ); }
34 
writeUInt(unsigned int i)35     virtual void writeUInt( unsigned int i )
36     { _out->write( (char*)&i, osgDB::INT_SIZE ); }
37 
writeLong(long l)38     virtual void writeLong( long l )
39     {
40         // On 64-bit systems a long may not be the same size as the file value
41         int32_t value=(int32_t)l;
42         _out->write( (char*)&value, osgDB::LONG_SIZE );
43     }
44 
writeULong(unsigned long l)45     virtual void writeULong( unsigned long l )
46     {
47         // On 64-bit systems a long may not be the same size as the file value
48         uint32_t value=(int32_t)l;
49         _out->write( (char*)&value, osgDB::LONG_SIZE );
50     }
51 
writeInt64(int64_t ll)52     virtual void writeInt64( int64_t ll )
53     {_out->write( (char*)&ll, osgDB::INT64_SIZE );}
54 
writeUInt64(uint64_t ull)55     virtual void writeUInt64( uint64_t ull )
56     {_out->write( (char*)&ull, osgDB::INT64_SIZE );}
57 
writeInt(long long ll)58     virtual void writeInt( long long ll )
59     { _out->write( (char*)&ll, osgDB::INT64_SIZE ); }
60 
writeUInt(unsigned long long ull)61     virtual void writeUInt( unsigned long long ull )
62     { _out->write( (char*)&ull, osgDB::INT64_SIZE ); }
63 
writeFloat(float f)64     virtual void writeFloat( float f )
65     { _out->write( (char*)&f, osgDB::FLOAT_SIZE ); }
66 
writeDouble(double d)67     virtual void writeDouble( double d )
68     { _out->write((char*)&d, osgDB::DOUBLE_SIZE); }
69 
writeString(const std::string & s)70     virtual void writeString( const std::string& s )
71     {
72         int size = s.size();
73         _out->write( (char*)&size, osgDB::INT_SIZE );
74         _out->write( s.c_str(), s.size() );
75     }
76 
writeStream(std::ostream & (*)(std::ostream &))77     virtual void writeStream( std::ostream& (* /*fn*/)(std::ostream&) ) {}
78 
writeBase(std::ios_base & (*)(std::ios_base &))79     virtual void writeBase( std::ios_base& (* /*fn*/)(std::ios_base&) ) {}
80 
writeGLenum(const osgDB::ObjectGLenum & value)81     virtual void writeGLenum( const osgDB::ObjectGLenum& value )
82     { GLenum e = value.get(); _out->write((char*)&e, osgDB::GLENUM_SIZE); }
83 
writeProperty(const osgDB::ObjectProperty & prop)84     virtual void writeProperty( const osgDB::ObjectProperty& prop )
85     { if (prop._mapProperty) _out->write((char*)&(prop._value), osgDB::INT_SIZE); }
86 
writeMark(const osgDB::ObjectMark & mark)87     virtual void writeMark( const osgDB::ObjectMark& mark )
88     {
89         if ( _supportBinaryBrackets )
90         {
91             if (getOutputStream() && getOutputStream()->getFileVersion() > 148)
92             {
93                 if ( mark._name=="{" )
94                 {
95                     uint64_t size = 0;
96                     _beginPositions.push_back( _out->tellp() );
97                     _out->write( (char*)&size, osgDB::INT64_SIZE );
98                 }
99                 else if ( mark._name=="}" && _beginPositions.size()>0 )
100                 {
101                     std::streampos pos = _out->tellp(), beginPos = _beginPositions.back();
102                     _beginPositions.pop_back();
103                     _out->seekp( beginPos );
104 
105                     std::streampos size64 = pos - beginPos;
106                     uint64_t size = (uint64_t) size64;
107                     _out->write( (char*)&size, osgDB::INT64_SIZE);
108                     _out->seekp( pos );
109                 }
110             }
111             else
112             {
113                 if ( mark._name=="{" )
114                 {
115                     int size = 0;
116                     _beginPositions.push_back( _out->tellp() );
117                     _out->write( (char*)&size, osgDB::INT_SIZE );
118                 }
119                 else if ( mark._name=="}" && _beginPositions.size()>0 )
120                 {
121                     std::streampos pos = _out->tellp(), beginPos = _beginPositions.back();
122                     _beginPositions.pop_back();
123                     _out->seekp( beginPos );
124 
125                     std::streampos size64 = pos - beginPos;
126                     int size = (int) size64;
127                     _out->write( (char*)&size, osgDB::INT_SIZE);
128                     _out->seekp( pos );
129                 }
130             }
131         }
132     }
133 
writeCharArray(const char * s,unsigned int size)134     virtual void writeCharArray( const char* s, unsigned int size )
135     { if ( size>0 ) _out->write( s, size ); }
136 
writeWrappedString(const std::string & str)137     virtual void writeWrappedString( const std::string& str )
138     { writeString( str ); }
139 
140 protected:
141     std::vector<std::streampos> _beginPositions;
142 };
143 
144 class BinaryInputIterator : public osgDB::InputIterator
145 {
146 public:
BinaryInputIterator(std::istream * istream,int byteSwap)147     BinaryInputIterator( std::istream* istream, int byteSwap )
148     {
149         _in = istream;
150         setByteSwap(byteSwap);
151     }
152 
~BinaryInputIterator()153     virtual ~BinaryInputIterator() {}
154 
isBinary()155     virtual bool isBinary() const { return true; }
156 
readBool(bool & b)157     virtual void readBool( bool& b )
158     {
159         char c = 0;
160         _in->read( &c, osgDB::CHAR_SIZE );
161         b = (c!=0);
162     }
163 
readChar(char & c)164     virtual void readChar( char& c )
165     { _in->read( &c, osgDB::CHAR_SIZE ); }
166 
readSChar(signed char & c)167     virtual void readSChar( signed char& c )
168     { _in->read( (char*)&c, osgDB::CHAR_SIZE ); }
169 
readUChar(unsigned char & c)170     virtual void readUChar( unsigned char& c )
171     { _in->read( (char*)&c, osgDB::CHAR_SIZE ); }
172 
readShort(short & s)173     virtual void readShort( short& s )
174     {
175         _in->read( (char*)&s, osgDB::SHORT_SIZE );
176         if ( _byteSwap ) osg::swapBytes( (char*)&s, osgDB::SHORT_SIZE );
177     }
178 
readUShort(unsigned short & s)179     virtual void readUShort( unsigned short& s )
180     {
181         _in->read( (char*)&s, osgDB::SHORT_SIZE );
182         if ( _byteSwap ) osg::swapBytes( (char*)&s, osgDB::SHORT_SIZE );
183     }
184 
readInt(int & i)185     virtual void readInt( int& i )
186     {
187         _in->read( (char*)&i, osgDB::INT_SIZE );
188         if ( _byteSwap ) osg::swapBytes( (char*)&i, osgDB::INT_SIZE );
189     }
190 
readUInt(unsigned int & i)191     virtual void readUInt( unsigned int& i )
192     {
193         _in->read( (char*)&i, osgDB::INT_SIZE );
194         if ( _byteSwap ) osg::swapBytes( (char*)&i, osgDB::INT_SIZE );
195     }
196 
readLong(long & l)197     virtual void readLong( long& l )
198     {
199         // On 64-bit systems a long may not be the same size as the file value
200         int32_t value;
201         _in->read( (char*)&value, osgDB::LONG_SIZE );
202         if ( _byteSwap ) osg::swapBytes( (char*)&value, osgDB::LONG_SIZE );
203         l = (long)value;
204     }
205 
readULong(unsigned long & l)206     virtual void readULong( unsigned long& l )
207     {
208         uint32_t value;
209         _in->read( (char*)&value, osgDB::LONG_SIZE );
210         if ( _byteSwap ) osg::swapBytes( (char*)&value, osgDB::LONG_SIZE );
211         l = (unsigned long)value;
212     }
213 
readFloat(float & f)214     virtual void readFloat( float& f )
215     {
216         _in->read( (char*)&f, osgDB::FLOAT_SIZE );
217         if ( _byteSwap ) osg::swapBytes( (char*)&f, osgDB::FLOAT_SIZE );
218     }
219 
readDouble(double & d)220     virtual void readDouble( double& d )
221     {
222         _in->read( (char*)&d, osgDB::DOUBLE_SIZE );
223         if ( _byteSwap ) osg::swapBytes( (char*)&d, osgDB::DOUBLE_SIZE );
224     }
225 
readString(std::string & s)226     virtual void readString( std::string& s )
227     {
228         int size = 0;
229         readInt( size );
230         if ( size>0 )
231         {
232             s.resize( size );
233             _in->read( (char*)s.c_str(), size );
234         }
235         else if ( size<0 )
236         {
237             throwException( "InputStream::readString() error, negative string size read." );
238         }
239     }
240 
readStream(std::istream & (*)(std::istream &))241     virtual void readStream( std::istream& (* /*fn*/)(std::istream&) ) {}
242 
readBase(std::ios_base & (*)(std::ios_base &))243     virtual void readBase( std::ios_base& (* /*fn*/)(std::ios_base&) ) {}
244 
readGLenum(osgDB::ObjectGLenum & value)245     virtual void readGLenum( osgDB::ObjectGLenum& value )
246     {
247         GLenum e = 0;
248         _in->read( (char*)&e, osgDB::GLENUM_SIZE );
249         if ( _byteSwap ) osg::swapBytes( (char*)&e, osgDB::GLENUM_SIZE );
250         value.set( e );
251     }
252 
readProperty(osgDB::ObjectProperty & prop)253     virtual void readProperty( osgDB::ObjectProperty& prop )
254     {
255         int value = 0;
256         if ( prop._mapProperty )
257         {
258             _in->read( (char*)&value, osgDB::INT_SIZE );
259             if ( _byteSwap ) osg::swapBytes( (char*)&value, osgDB::INT_SIZE );
260         }
261         prop.set( value );
262     }
263 
readMark(osgDB::ObjectMark & mark)264     virtual void readMark( osgDB::ObjectMark& mark )
265     {
266         if ( _supportBinaryBrackets )
267         {
268             if ( mark._name=="{" )
269             {
270                 _beginPositions.push_back( _in->tellg() );
271 
272                 // since version 149 (osg version > 3.5.6) size is expressed
273                 // on 8 bytes rather than 4 bytes,
274                 // to accommodate any block size.
275                 if (getInputStream() && getInputStream()->getFileVersion() > 148)
276                 {
277                    uint64_t size = 0;
278                    _in->read( (char*)&size, osgDB::INT64_SIZE);
279                    if ( _byteSwap ) osg::swapBytes( (char*)&size, osgDB::INT64_SIZE);
280                    _blockSizes.push_back( size );
281                 }
282                 else
283                 {
284                    int size = 0;
285                    _in->read( (char*)&size, osgDB::INT_SIZE);
286                    if ( _byteSwap ) osg::swapBytes( (char*)&size, osgDB::INT_SIZE);
287                    _blockSizes.push_back( size );
288                 }
289             }
290             else if ( mark._name=="}" && _beginPositions.size()>0 )
291             {
292                 _beginPositions.pop_back();
293                 _blockSizes.pop_back();
294             }
295         }
296     }
297 
readCharArray(char * s,unsigned int size)298     virtual void readCharArray( char* s, unsigned int size )
299     { if ( size>0 ) _in->read( s, size ); }
300 
readWrappedString(std::string & str)301     virtual void readWrappedString( std::string& str )
302     { readString( str ); }
303 
advanceToCurrentEndBracket()304     virtual void advanceToCurrentEndBracket()
305     {
306         if ( _supportBinaryBrackets && _beginPositions.size()>0 )
307         {
308             std::streampos position(_beginPositions.back());
309             position += _blockSizes.back();
310             _in->seekg( position );
311             _beginPositions.pop_back();
312             _blockSizes.pop_back();
313         }
314     }
315 
316 protected:
317     std::vector<std::streampos> _beginPositions;
318     std::vector<std::streampos> _blockSizes;
319 };
320 
321 #endif
322