2
// Copyright (C) 2008 Free Software Foundation, Inc.
4
// This program is free software; you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation; either version 3 of the License, or
7
// (at your option) any later version.
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU General Public License for more details.
14
// You should have received a copy of the GNU General Public License
15
// along with this program; if not, write to the Free Software
16
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
#include <boost/cstdint.hpp>
27
using namespace gnash;
33
// convert an ascii hex digit to a number.
34
// param is hex digit.
35
// returns a decimal digit.
37
hex2digit (Network::byte_t digit)
42
if (digit >= '0' && digit <= '9')
44
if (digit >= 'a' && digit <= 'f')
45
return digit - 'a' + 10;
46
if (digit >= 'A' && digit <= 'F')
47
return digit - 'A' + 10;
49
// shouldn't ever get this far
53
// Convert the hex array pointed to by buf into binary to be placed in mem
55
Buffer::hex2mem(const char *str)
57
size_t count = strlen(str);
58
Network::byte_t ch = 0;
59
_ptr = new Buffer((count/3)+1);
62
Network::byte_t *strdata = const_cast<Network::byte_t *>(reinterpret_cast<const Network::byte_t *>(str));
64
for (size_t i=0; i<count; i++) {
65
if (*strdata == ' ') { // skip spaces.
69
ch = hex2digit(*strdata++) << 4;
70
ch |= hex2digit(*strdata++);
78
Buffer::init(size_t nbytes)
80
// GNASH_REPORT_FUNCTION;
82
_ptr = new Network::byte_t[nbytes];
90
#ifdef USE_STATS_BUFFERS
91
clock_gettime (CLOCK_REALTIME, &_stamp);
100
// GNASH_REPORT_FUNCTION;
101
_nbytes = gnash::NETBUFSIZE;
102
init(gnash::NETBUFSIZE);
105
// Create with a size other than the default
106
Buffer::Buffer(size_t nbytes)
110
// GNASH_REPORT_FUNCTION;
115
// Delete the allocate memory
118
// GNASH_REPORT_FUNCTION;
120
#ifdef USE_STATS_BUFFERS
122
clock_gettime (CLOCK_REALTIME, &now);
123
log_debug("Buffer %x (%d) stayed in queue for %f seconds",
124
(void *)_ptr, _nbytes,
125
(float)((now.tv_sec - _stamp.tv_sec) + ((now.tv_nsec - _stamp.tv_nsec)/1e9)));
133
// Put data into the buffer
135
Buffer::copy(Network::byte_t *data, size_t nbytes)
137
// GNASH_REPORT_FUNCTION;
138
std::copy(data, data + nbytes, _ptr);
139
_seekptr = _ptr + nbytes;
143
Buffer::copy(const string &str)
145
// GNASH_REPORT_FUNCTION;
146
std::copy(str.begin(), str.end(), _ptr);
147
_seekptr = _ptr + str.size();
151
Buffer::copy(boost::uint16_t length)
153
Network::byte_t *data = reinterpret_cast<Network::byte_t *>(&length);
154
std::copy(data, data + sizeof(boost::uint16_t), _ptr);
155
_seekptr = _ptr + sizeof(boost::uint16_t);
159
Buffer::copy(double num)
161
// GNASH_REPORT_FUNCTION;
162
Network::byte_t *ptr = reinterpret_cast<Network::byte_t *>(&num);
163
std::copy(ptr, ptr + amf::AMF0_NUMBER_SIZE, _ptr);
164
_seekptr = _ptr + amf::AMF0_NUMBER_SIZE;
168
Buffer::copy(Network::byte_t val)
170
GNASH_REPORT_FUNCTION;
172
_seekptr = _ptr + sizeof(bool);
177
Buffer::copy(bool val)
179
GNASH_REPORT_FUNCTION;
180
return copy(static_cast<Network::byte_t>(val));
185
Buffer::append(boost::uint16_t length)
187
// GNASH_REPORT_FUNCTION;
189
if ((_seekptr + sizeof(boost::uint16_t)) <= (_ptr + _nbytes)) {
190
Network::byte_t *data = reinterpret_cast<Network::byte_t *>(&length);
191
std::copy(data, data + sizeof(boost::uint16_t), _seekptr);
192
_seekptr += sizeof(boost::uint16_t);
199
Buffer::append(gnash::Network::byte_t *data, size_t nbytes)
201
// GNASH_REPORT_FUNCTION;
203
if ((_seekptr + nbytes) <= (_ptr + _nbytes)) {
204
std::copy(data, data + nbytes, _seekptr);
212
Buffer::append(double num)
214
// GNASH_REPORT_FUNCTION;
215
if ((_seekptr + sizeof(double)) <= (_ptr + _nbytes)) {
216
Network::byte_t *ptr = reinterpret_cast<Network::byte_t *>(&num);
217
std::copy(ptr, ptr + amf::AMF0_NUMBER_SIZE, _seekptr);
218
_seekptr += amf::AMF0_NUMBER_SIZE;
225
Buffer::append(bool val)
227
// GNASH_REPORT_FUNCTION;
228
if ((_seekptr + sizeof(bool)) <= (_ptr + _nbytes)) {
230
_seekptr += sizeof(bool);
237
Buffer::append(boost::uint32_t num)
239
// GNASH_REPORT_FUNCTION;
240
Network::byte_t *ptr = reinterpret_cast< Network::byte_t *>(&num);
241
return append(ptr, sizeof(boost::uint32_t));
245
Buffer::append(Network::byte_t byte)
247
// GNASH_REPORT_FUNCTION;
248
if ((_seekptr + sizeof(gnash::Network::byte_t)) <= (_ptr + _nbytes)) {
250
_seekptr += sizeof(gnash::Network::byte_t);
257
Buffer::append(const std::string &str)
259
// GNASH_REPORT_FUNCTION;
260
if ((_seekptr + str.size()) <= (_ptr + _nbytes)) {
261
std::copy(str.begin(), str.end(), _seekptr);
262
_seekptr += str.size();
269
Buffer::append(amf::Element::amf0_type_e type)
271
return append(static_cast<Network::byte_t>(type));
275
Buffer::append(Buffer &buf)
277
// GNASH_REPORT_FUNCTION;
282
Buffer::append(Buffer *buf)
284
// GNASH_REPORT_FUNCTION;
285
size_t diff = _seekptr - _ptr;
287
if (buf->size() > (_nbytes - diff)) {
288
resize(buf->size() + diff);
291
std::copy(buf->begin(), buf->end(), _seekptr);
292
_seekptr += buf->size();
297
// make ourselves be able to appended too. If the source
298
// buffer is larger than the current buffer has room for,
299
// resize ourselves (which copies the data too) to make
301
// note that using this may have a performance hit due to
302
// the resize operation, which has to copy data.
304
Buffer::operator+=(Buffer &buf)
306
return operator+=(&buf);
310
Buffer::operator+=(Buffer *buf)
312
// GNASH_REPORT_FUNCTION;
314
if (buf->size() >= _nbytes) {
315
diff = _seekptr - _ptr;
316
resize(buf->size() + diff);
319
if ((_seekptr + buf->size()) <= (_ptr + _nbytes)) {
320
std::copy(buf->begin(), buf->end(), _seekptr);
321
_seekptr += buf->size();
327
Buffer::operator+=(char byte)
329
// GNASH_REPORT_FUNCTION;
330
return operator+=(static_cast<Network::byte_t>(byte));
334
Buffer::operator+=(Network::byte_t byte)
336
// GNASH_REPORT_FUNCTION;
337
if ((_seekptr + 1) <= (_ptr + _nbytes)) {
339
_seekptr += sizeof(char);
344
// make ourselves be able to be copied.
346
Buffer::operator=(Buffer *buf)
348
// GNASH_REPORT_FUNCTION;
349
if (buf->size() > _nbytes) {
353
std::copy(buf->begin(), buf->end(), _ptr);
354
_seekptr += buf->size();
360
Buffer::operator=(Buffer &buf)
362
// GNASH_REPORT_FUNCTION;
363
if (buf.size() != _nbytes) {
367
std::copy(buf.begin(), buf.end(), _ptr);
372
// Check to see if two Buffer objects are identical
374
Buffer::operator==(Buffer *buf)
376
// GNASH_REPORT_FUNCTION;
377
Network::byte_t *bufptr = buf->reference();
378
if (buf->size() == _nbytes) {
379
if (memcmp(bufptr, _ptr, _nbytes) == 0) {
387
Buffer::operator==(Buffer &buf)
389
// GNASH_REPORT_FUNCTION;
390
// Network::byte_t *bufptr = buf.reference();
393
// if (buf.size() == _nbytes){
394
// if (memcmp(bufptr, _ptr, _nbytes) == 0) {
399
return operator==(&buf);
403
Buffer::find(Network::byte_t *b, size_t size)
405
// GNASH_REPORT_FUNCTION;
406
for (size_t i=0; i< _nbytes; i++) {
407
if (memcmp((_ptr + i), b, size) == 0) {
415
Buffer::find(Network::byte_t c)
417
// GNASH_REPORT_FUNCTION;
418
for (size_t i=0; i< _nbytes; i++) {
419
if (*(_ptr + i) == c) {
427
Buffer::remove(Network::byte_t c)
429
// GNASH_REPORT_FUNCTION;
430
Network::byte_t *start = find(c);
432
log_debug("Byte is at %x", (void *)start);
438
std::copy(start + 1, end(), start);
446
Buffer::remove(int start)
448
// GNASH_REPORT_FUNCTION;
449
std::copy((_ptr + start + 1), end(), (_ptr + start)),
456
Buffer::remove(int start, int stop)
458
// GNASH_REPORT_FUNCTION;
459
std::copy((_ptr + stop + 1), end(), (_ptr + start)),
461
_nbytes -= stop-start;
465
// Just reset to having no data, but still having storage
469
// GNASH_REPORT_FUNCTION;
471
memset(_ptr, 0, _nbytes);
476
// Resize the buffer that holds the data.
477
// Resize the buffer that holds the data.
481
// GNASH_REPORT_FUNCTION;
482
return resize(_seekptr - _ptr);
486
Buffer::resize(size_t size)
488
// GNASH_REPORT_FUNCTION;
489
// Allocate a new memory block
493
size_t diff =_seekptr - _ptr;
494
Network::byte_t *tmp = new Network::byte_t[size];
495
// The size is the same, don't do anything.
496
if (size == _nbytes) {
499
// And copy ourselves into it
500
if (size > _nbytes) {
501
std::copy(_ptr, _ptr + _nbytes, tmp);
502
// Delete the old block, it's unused now
504
// Make the memory block use the new space
506
// Make the seekptr point into the new space with the correct offset
507
_seekptr = tmp + diff;
509
if (size < _nbytes) {
510
std::copy(_ptr, _ptr + size, tmp);
511
// Delete the old block, it's unused now
513
// Make the memory block use the new space
515
// Make the seekptr point into the new space with the correct offset
516
_seekptr = _ptr + size;
528
cerr << "Buffer is " << _nbytes << " bytes at " << (void *)_ptr << endl;
529
if (_nbytes < 0xffff) {
530
cerr << gnash::hexify((unsigned char *)_ptr, _nbytes, false) << endl;
531
cerr << gnash::hexify((unsigned char *)_ptr, _nbytes, true) << endl;
533
cerr << "ERROR: Buffer size out of range!" << endl;
538
} // end of amf namespace
542
// indent-tabs-mode: t