1 // CodeStream.cpp A class which allows bounds-checked reading from a char array
2 //
3 //   Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
4 //   Free Software 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
19 
20 #include "CodeStream.h"
21 #include <iostream>
22 
23 namespace gnash {
24 
25 /// Read a variable length encoded 32 bit unsigned integer
26 std::uint32_t
read_V32()27 CodeStream::read_V32()
28 {
29 	char data;
30 
31 	read(&data,1);
32 	std::uint32_t result = data;
33 	if (!(result & 0x00000080))	return result;
34 
35 	read(&data,1);
36 	result = (result & 0x0000007F) | data << 7;
37 	if (!(result & 0x00004000)) return result;
38 
39 	read(&data,1);
40 	result = (result & 0x00003FFF) | data << 14;
41 	if (!(result & 0x00200000)) return result;
42 
43 	read(&data,1);
44 	result = (result & 0x001FFFFF) | data << 21;
45 	if (!(result & 0x10000000)) return result;
46 
47 	read(&data,1);
48 	return (result & 0x0FFFFFFF) | data << 28;
49 
50 }
51 
52 /// Read an opcode for ActionScript 3
53 std::uint8_t
read_as3op()54 CodeStream::read_as3op()
55 {
56 	char data;
57 	read(&data,1);
58 	if(eof()){
59 		return 0;
60 	}
61 	else{
62 		return static_cast<std::uint8_t> (data);
63 	}
64 }
65 
66 /// Change the current position by a relative value.
67 void
seekBy(int change)68 CodeStream::seekBy(int change)
69 {
70 	seekg(change,ios_base::cur);
71 }
72 
73 /// Set the current position to an absolute value (relative to the start)
74 void
seekTo(unsigned int set)75 CodeStream::seekTo(unsigned int set)
76 {
77 	seekg(set);
78 }
79 
80 //TODO: Is there a better way to read a 24 bit signed int?
81 std::int32_t
read_S24()82 CodeStream::read_S24()
83 {
84 	char buffer[3];
85 	read(buffer,3);
86 	uint32_t result = buffer[0] & 0xFF;
87 	result |= buffer[1] & 0xFF << 8;
88 	result |= buffer[2] & 0xFF << 16;
89 	if (result & (1 << 23)) {
90 	       	result |= -1 << 24;
91    	}
92 
93 	return static_cast<std::int32_t>(result);
94 }
95 
96 /// Read a signed 8-bit character.
97 int8_t
read_s8()98 CodeStream::read_s8()
99 {
100 	char data;
101 	read(&data,1);
102 	return static_cast<int8_t> (data);
103 }
104 
105 /// Read an unsigned 8-bit character.
106 std::uint8_t
read_u8()107 CodeStream::read_u8()
108 {
109 	char data;
110 	read(&data,1);
111 	return static_cast<std::uint8_t> (data);
112 }
113 
114 /// Same as read_V32(), but doesn't bother with the arithmetic for
115 /// calculating the value.
116 void
skip_V32()117 CodeStream::skip_V32()
118 {
119 	// shortcut evalution is mandated as standard.
120 	//TODO: Make this more efficient.
121 // 	if ((*mCurrent++ & 0x80) && (*mCurrent++ & 0x80) && (*mCurrent++ &0x80)
122 // 		&& (*mCurrent++ & 0x80) && (*mCurrent++ & 0x80)){
123 // 		return;
124 // 	}
125 	read_V32();
126 	return;
127 
128 }
129 
130 } // namespace gnash
131 
132