update version to the release
[gnash.git] / libcore / SWFStream.h
blobdbfe445929a02212121f7eab16fc7f7d5c52c99e
1 // stream.h - SWF stream reading class, for Gnash
2 //
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
4 // Foundation, Inc
5 //
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.
10 //
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.
15 //
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
23 #include "SWF.h"
24 #include "dsodefs.h" // still neded ?
25 #include "GnashException.h"
27 #include <string>
28 #include <sstream>
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
43 namespace gnash {
44 class IOChannel;
47 namespace gnash {
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.
53 ///
54 /// Provides 'aligned' and 'bitwise' read functions:
55 /// - aligned reads always start on a byte boundary
56 /// - bitwise reads can cross byte boundaries
57 ///
58 class DSOEXPORT SWFStream
60 public:
61 SWFStream(IOChannel* input);
62 ~SWFStream();
64 /// \brief
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.
69 /// bitwise read
70 ///
71 unsigned read_uint(unsigned short bitcount);
73 /// \brief
74 /// Reads a single bit off the stream
75 /// and returns it.
77 /// bitwise read
78 ///
79 bool read_bit();
81 /// \brief
82 /// Reads a bit-packed little-endian signed integer
83 /// from the stream. The given bitcount determines the
84 /// number of bits to read.
86 /// bitwise read
87 ///
88 int read_sint(unsigned short bitcount);
90 /// Read a 16.16 fixed point signed value
92 /// aligned read
93 ///
94 float read_fixed();
96 /// Read a 16.16 fixed point unsigned value
98 /// aligned read
99 ///
100 float read_ufixed();
102 /// Read a 8.8 fixed point unsigned value
104 /// aligned read
106 float read_short_ufixed();
108 /// Read a 8.8 fixed point signed value
110 /// aligned read
112 float read_short_sfixed();
114 /// Read a 16bit (1:sign 5:exp 10:mantissa) floating point value
116 /// aligned read
118 float read_short_float();
120 /// Read a 32bit (1:sign 8:exp 23:mantissa) floating point value
122 /// aligned read
124 float read_long_float();
126 /// Read a 64-bit double value
128 /// aligned read
130 double read_d64();
132 /// Consume all bits of current byte
134 /// This method is implicitly called by all 'aligned' reads.
136 /// NOTE:
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.
141 void align()
143 m_unused_bits=0;
144 // m_current_byte = 0; // this is not needed
147 /// Read <count> bytes from the source stream and copy that data to <buf>.
149 /// aligned read
151 unsigned read(char *buf, unsigned count);
153 /// Read a aligned unsigned 8-bit value from the stream.
155 /// aligned read
157 boost::uint8_t read_u8();
159 /// Read a aligned signed 8-bit value from the stream.
161 /// aligned read
163 boost::int8_t read_s8();
165 /// Read a aligned unsigned 16-bit value from the stream.
167 /// aligned read
169 boost::uint16_t read_u16();
171 /// Read a aligned signed 16-bit value from the stream.
173 /// aligned read
175 boost::int16_t read_s16();
177 /// Read a aligned unsigned 32-bit value from the stream.
179 /// aligned read
181 boost::uint32_t read_u32();
183 /// \brief
184 /// Read a aligned signed 32-bit value from the stream.
186 /// aligned read
188 boost::int32_t read_s32();
190 /// \brief
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.
195 /// aligned read
197 boost::uint32_t read_V32()
199 ensureBytes(1);
200 boost::uint32_t res = read_u8();
201 if (!(res & 0x00000080)) return res;
203 ensureBytes(1);
204 res = (res & 0x0000007F) | read_u8() << 7;
205 if (!(res & 0x00004000)) return res;
207 ensureBytes(1);
208 res = (res & 0x00003FFF) | read_u8() << 14;
209 if (!(res & 0x00200000)) return res;
211 ensureBytes(1);
212 res = (res & 0x001FFFFF) | read_u8() << 21;
213 if (!(res & 0x10000000)) return res;
215 ensureBytes(1);
216 res = (res & 0x0FFFFFFF) | read_u8() << 28;
217 return res;
220 /// \brief
221 /// Skip a variable length unsigned 32-bit value in the stream.
222 /// This is faster than doing the bitwise arithmetic of full reading.
224 /// aligned read
226 void skip_V32()
228 ensureBytes(1);
229 if (!(read_u8() & 0x80)) return;
230 ensureBytes(1);
231 if (!(read_u8() & 0x80)) return;
232 ensureBytes(1);
233 if (!(read_u8() & 0x80)) return;
234 ensureBytes(1);
235 if (!(read_u8() & 0x80)) return;
236 ensureBytes(1);
237 static_cast<void> (read_u8());
240 /// \brief
241 /// Read a length in a byte or three.
243 /// If the byte == 0xff, read the lenght in
244 /// next two bytes.
246 /// Takes care of integrity check (ensureByte)
248 /// aligned read
250 unsigned read_variable_count()
252 ensureBytes(1);
253 unsigned count = read_u8();
254 if (count == 0xFF)
256 ensureBytes(2);
257 count = read_u16();
259 return count;
262 /// \brief
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.
267 /// aligned read
269 /// Will throw ParserException if no terminating null is found within
270 /// tag boundaries
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.
277 /// @param to
278 /// Output argument. Any previous value will be overriden.
280 /// aligned read
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.
289 /// @param len
290 /// Length of string to read.
292 /// @param to
293 /// Output argument. Any previous value will be overriden.
295 /// aligned read
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.
303 /// NOTE:
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
308 /// (already 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.
330 /// aligned read
332 SWF::TagType open_tag();
334 /// Seek to the end of the most-recently-opened tag.
335 void close_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());
366 /// \brief
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);
378 /// \brief
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());
400 #endif
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.
419 void consumeInput();
421 private:
423 IOChannel* m_input;
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;
433 } // namespace gnash
436 #endif // GNASH_STREAM_H
439 // Local Variables:
440 // mode: C++
441 // c-basic-offset: 8
442 // tab-width: 8
443 // indent-tabs-mode: t
444 // End: