Backslash ${prefix} for kde3 too...
[gnash.git] / libbase / AMF.cpp
blob9d4b87f6d84f9c81bbf6c4b3ed4476a0f46fdb55
1 // AMFConverter.h High-level functions for converting as_values to AMF.
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 // This file provides high-level function objects for converting ActionScript
21 // values to AMF buffers and vice-versa.
23 #include <map>
24 #include <algorithm>
26 #include "log.h"
27 #include "SimpleBuffer.h"
28 #include "AMF.h"
30 // Define this macro to make AMF parsing verbose
31 //#define GNASH_DEBUG_AMF_DESERIALIZE 1
33 // Define this macto to make AMF writing verbose
34 // #define GNASH_DEBUG_AMF_SERIALIZE 1
36 namespace gnash {
37 namespace amf {
39 namespace {
40 /// Swap bytes in raw data.
42 /// This only swaps bytes if the host byte order is little endian.
43 ///
44 /// @param word The address of the data to byte swap.
45 /// @param size The number of bytes in the data.
46 void swapBytes(void* word, size_t size);
49 bool
50 readBoolean(const boost::uint8_t*& pos, const boost::uint8_t* _end)
52 if (pos == _end) {
53 throw AMFException("Read past _end of buffer for boolean type");
56 const bool val = *pos;
57 ++pos;
58 #ifdef GNASH_DEBUG_AMF_DESERIALIZE
59 log_debug("amf0 read bool: %d", val);
60 #endif
61 return val;
64 double
65 readNumber(const boost::uint8_t*& pos, const boost::uint8_t* end)
68 if (end - pos < 8) {
69 throw AMFException("Read past _end of buffer for number type");
72 double d;
73 // TODO: may we avoid a copy and swapBytes call
74 // by bitshifting b[0] trough b[7] ?
75 std::copy(pos, pos + 8, reinterpret_cast<char*>(&d));
76 pos += 8;
77 swapBytes(&d, 8);
79 #ifdef GNASH_DEBUG_AMF_DESERIALIZE
80 log_debug("amf0 read double: %e", dub);
81 #endif
83 return d;
86 std::string
87 readString(const boost::uint8_t*& pos, const boost::uint8_t* end)
89 if (end - pos < 2) {
90 throw AMFException("Read past _end of buffer for string length");
93 const boost::uint16_t si = readNetworkShort(pos);
94 pos += 2;
96 if (end - pos < si) {
97 throw AMFException("Read past _end of buffer for string type");
100 const std::string str(reinterpret_cast<const char*>(pos), si);
101 pos += si;
102 #ifdef GNASH_DEBUG_AMF_DESERIALIZE
103 log_debug("amf0 read string: %s", str);
104 #endif
105 return str;
108 std::string
109 readLongString(const boost::uint8_t*& pos, const boost::uint8_t* end)
111 if (end - pos < 4) {
112 throw AMFException("Read past _end of buffer for long string length");
115 const boost::uint32_t si = readNetworkLong(pos);
116 pos += 4;
117 if (static_cast<boost::uint32_t>(end - pos) < si) {
118 throw AMFException("Read past _end of buffer for long string type");
121 const std::string str(reinterpret_cast<const char*>(pos), si);
122 pos += si;
124 #ifdef GNASH_DEBUG_AMF_DESERIALIZE
125 log_debug("amf0 read long string: %s", str);
126 #endif
128 return str;
132 void
133 writePlainString(SimpleBuffer& buf, const std::string& str, Type t)
135 const size_t len = str.size();
136 switch (t) {
137 default:
138 log_error("writePlainString called with invalid type!");
139 return;
141 case LONG_STRING_AMF0:
142 buf.appendNetworkLong(len);
143 break;
145 case STRING_AMF0:
146 buf.appendNetworkShort(len);
147 break;
150 buf.append(str.c_str(), len);
153 void
154 writePlainNumber(SimpleBuffer& buf, double d)
156 swapBytes(&d, 8);
157 buf.append(&d, 8);
160 void
161 write(SimpleBuffer& buf, const std::string& str)
163 Type t = str.size() < 65536 ? STRING_AMF0 : LONG_STRING_AMF0;
164 buf.appendByte(t);
165 writePlainString(buf, str, t);
168 void
169 write(SimpleBuffer& buf, double d)
171 buf.appendByte(NUMBER_AMF0);
172 writePlainNumber(buf, d);
175 void
176 write(SimpleBuffer& buf, bool b)
178 buf.appendByte(BOOLEAN_AMF0);
179 buf.appendByte(b ? 1 : 0);
182 namespace {
184 void
185 swapBytes(void* word, size_t size)
187 union {
188 boost::uint16_t s;
189 struct {
190 boost::uint8_t c0;
191 boost::uint8_t c1;
192 } c;
193 } u;
195 u.s = 1;
196 if (u.c.c0 == 0) {
197 // Big-endian machine: do nothing
198 return;
201 // Little-endian machine: byte-swap the word
202 // A conveniently-typed pointer to the source data
203 boost::uint8_t *x = static_cast<boost::uint8_t *>(word);
205 // Handles odd as well as even counts of bytes
206 std::reverse(x, x + size);
209 } // unnamed namespace
211 } // namespace amf
212 } // namespace gnash