1 // stream.h - SWF stream reading class, for Gnash
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
4 // Free Software Foundation, Inc
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #ifndef GNASH_STREAM_H
21 #define GNASH_STREAM_H
24 #include "dsodefs.h" // still neded ?
25 #include "GnashException.h"
29 #include <vector> // for composition
30 #include <boost/cstdint.hpp> // for boost::?int??_t
32 // Define the following macro if you want to want Gnash parser
33 // to assume the underlying SWF is well-formed. It would make
34 // parsing faster, but might result in horrible behaviour with
35 // malformed SWFs (like taking up all system memory, keeping
36 // CPU busy for a long long time, or simply corrupting memory)
38 // This might be eventually set by a --disable-swf-checks or similar
39 // configure switch...
41 //#define GNASH_TRUST_SWF_INPUT
49 /// SWF stream wrapper class
51 /// This class is used for loading variable-length data
52 /// from a stream, and keeping track of SWF tag boundaries.
54 /// Provides 'aligned' and 'bitwise' read functions:
55 /// - aligned reads always start on a byte boundary
56 /// - bitwise reads can cross byte boundaries
58 class DSOEXPORT SWFStream
61 SWFStream(IOChannel
* input
);
65 /// Reads a bit-packed unsigned integer from the stream
66 /// and returns it. The given bitcount determines the
67 /// number of bits to read.
71 unsigned read_uint(unsigned short bitcount
);
74 /// Reads a single bit off the stream
82 /// Reads a bit-packed little-endian signed integer
83 /// from the stream. The given bitcount determines the
84 /// number of bits to read.
88 int read_sint(unsigned short bitcount
);
90 /// Read a 16.16 fixed point signed value
96 /// Read a 16.16 fixed point unsigned value
102 /// Read a 8.8 fixed point unsigned value
106 float read_short_ufixed();
108 /// Read a 8.8 fixed point signed value
112 float read_short_sfixed();
114 /// Read a 16bit (1:sign 5:exp 10:mantissa) floating point value
118 float read_short_float();
120 /// Read a 32bit (1:sign 8:exp 23:mantissa) floating point value
124 float read_long_float();
126 /// Read a 64-bit double value
132 /// Consume all bits of current byte
134 /// This method is implicitly called by all 'aligned' reads.
137 /// The position returned by tell() won't be changed
138 /// by calls to this function, altought any subsequent reads
139 /// will start on next byte. See tell() for more info.
144 // m_current_byte = 0; // this is not needed
147 /// Read <count> bytes from the source stream and copy that data to <buf>.
151 unsigned read(char *buf
, unsigned count
);
153 /// Read a aligned unsigned 8-bit value from the stream.
157 boost::uint8_t read_u8();
159 /// Read a aligned signed 8-bit value from the stream.
163 boost::int8_t read_s8();
165 /// Read a aligned unsigned 16-bit value from the stream.
169 boost::uint16_t read_u16();
171 /// Read a aligned signed 16-bit value from the stream.
175 boost::int16_t read_s16();
177 /// Read a aligned unsigned 32-bit value from the stream.
181 boost::uint32_t read_u32();
184 /// Read a aligned signed 32-bit value from the stream.
188 boost::int32_t read_s32();
191 /// Read a variable length unsigned 32-bit value from the stream.
192 /// These values continue until either the high bit is not set or
193 /// until 5 bytes have been read.
197 boost::uint32_t read_V32()
200 boost::uint32_t res
= read_u8();
201 if (!(res
& 0x00000080)) return res
;
204 res
= (res
& 0x0000007F) | read_u8() << 7;
205 if (!(res
& 0x00004000)) return res
;
208 res
= (res
& 0x00003FFF) | read_u8() << 14;
209 if (!(res
& 0x00200000)) return res
;
212 res
= (res
& 0x001FFFFF) | read_u8() << 21;
213 if (!(res
& 0x10000000)) return res
;
216 res
= (res
& 0x0FFFFFFF) | read_u8() << 28;
221 /// Skip a variable length unsigned 32-bit value in the stream.
222 /// This is faster than doing the bitwise arithmetic of full reading.
229 if (!(read_u8() & 0x80)) return;
231 if (!(read_u8() & 0x80)) return;
233 if (!(read_u8() & 0x80)) return;
235 if (!(read_u8() & 0x80)) return;
237 static_cast<void> (read_u8());
241 /// Read a length in a byte or three.
243 /// If the byte == 0xff, read the lenght in
246 /// Takes care of integrity check (ensureByte)
250 unsigned read_variable_count()
253 unsigned count
= read_u8();
263 /// Reads a null-terminated string from the given file and
264 /// assigns it to the given std::string, overriding any
265 /// previous value of it.
269 /// Will throw ParserException if no terminating null is found within
271 void read_string(std::string
& to
);
273 /// Reads a sized string into a provided std::string.
275 /// Length of string is read from the first byte.
278 /// Output argument. Any previous value will be overriden.
282 /// Will throw ParserException if advertised length crosses tag boundaries
284 void read_string_with_length(std::string
& to
);
286 /// Reads a sized string into a provided std::string.
290 /// Length of string to read.
293 /// Output argument. Any previous value will be overriden.
297 /// Will throw ParserException if len crosses tag boundaries
299 void read_string_with_length(unsigned len
, std::string
& to
);
301 /// Return our current (byte) position in the input stream.
304 /// This is not necessarely the byte you'll read on next read.
305 /// - For bitwise reads the currenty byte will be used only if not
306 /// completely consumed. See align().
307 /// - For aligned reads the current byte will not be used
310 unsigned long tell();
312 /// Set the file position to the given value (byte aligned)
314 /// If we're scanning a tag, don't allow seeking past
315 /// the end or before start of it.
317 /// @return true on success, false on failure
318 /// Possible failures:
319 /// - given position is after end of stream.
320 /// - given position is after end of current tag, if any.
321 /// - given position is before start of current tag, if any.
323 bool seek(unsigned long pos
);
325 /// Return the file position of the end of the current tag.
326 unsigned long get_tag_end_position();
328 /// Open an SWF tag and return it's type.
332 SWF::TagType
open_tag();
334 /// Seek to the end of the most-recently-opened tag.
337 /// Discard given number of bytes
340 /// @return true on success, false on failure
341 /// Possible failures:
342 /// - skipping given number of bytes reaches end of stream.
343 /// - skipping given number of bytes reaches end of
344 /// current tag, if any.
346 /// WARNING: alignment is not specified here, the method uses
347 /// tell() which is known NOT to consider
348 /// a fully-read byte as already "skipped"
349 /// TODO: force alignment and see what happens !!
351 bool skip_bytes(unsigned num
)
353 // there's probably a better way, but
354 // it's the interface that counts atm
355 size_t curpos
= tell();
356 return seek(curpos
+num
);
359 /// Discard all bytes up to end of tag
360 void skip_to_tag_end()
362 // seek will call align...
363 seek(get_tag_end_position());
367 /// Ensure the requested number of bytes are available for an aligned read
368 /// in the currently opened tag.
370 /// Throws a ParserException on a short count.
371 /// This method should be called before any attempt to read
372 /// fields from the SWF.
374 /// NOTE: if GNASH_TRUST_SWF_INPUT is defined this function is a no-op
376 void ensureBytes(unsigned long needed
);
379 /// Ensure the requested number of bits are available for a bitwise read
380 /// in currently opened tag.
382 /// Throws a ParserException on a short count.
383 /// This method should be called before any attempt to read
384 /// bits from the SWF.
386 /// NOTE: if GNASH_TRUST_SWF_INPUT is defined this function is a no-op
388 void ensureBits(unsigned long needed
)
390 #ifndef GNASH_TRUST_SWF_INPUT
391 if ( _tagBoundsStack
.empty() ) return; // not in a tag (should we check file length ?)
392 unsigned long int bytesLeft
= get_tag_end_position() - tell();
393 unsigned long int bitsLeft
= (bytesLeft
*8)+m_unused_bits
;
394 if ( bitsLeft
< needed
)
396 std::stringstream ss
;
397 ss
<< "premature end of tag: need to read " << needed
<< " bytes, but only " << bitsLeft
<< " left in this tag";
398 throw ParserException(ss
.str());
403 /// Consume any pending input
405 /// This method is useful to force full consumption
406 /// of the SWFStream's underlying IOChannel for the
407 /// cases in which it is a pipe and a writer would
408 /// hang on it unless someone is reading.
410 /// This method will NOT be called automatically
411 /// on SWFStream destruction as in the current
412 /// design SWFStream does NOT own the underlying
413 /// IOChannel. TODO: rethink about ownership.
415 /// NOTE: the stream position will be updated by
416 /// this call, so that ::tell will basically
417 /// return the full input size.
424 boost::uint8_t m_current_byte
;
425 boost::uint8_t m_unused_bits
;
427 typedef std::pair
<unsigned long,unsigned long> TagBoundaries
;
428 // position of start and end of tag
429 std::vector
<TagBoundaries
> _tagBoundsStack
;
436 #endif // GNASH_STREAM_H
443 // indent-tabs-mode: t