Files
unison/src/common/buffer.cc

596 lines
18 KiB
C++
Raw Normal View History

/* -*- Mode:NS3; -*- */
2006-08-29 17:42:13 +02:00
/*
* Copyright (c) 2005,2006 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "buffer.h"
#include <cassert>
#include <iostream>
//#define TRACE(x) std::cout << x << std::endl;
#define TRACE(x)
2006-08-29 17:55:34 +02:00
namespace ns3 {
2006-08-29 17:42:13 +02:00
2006-09-05 12:54:53 +02:00
Buffer::BufferDataList Buffer::m_freeList;
uint32_t Buffer::m_maxTotalAddStart = 0;
uint32_t Buffer::m_maxTotalAddEnd = 0;
2006-08-29 17:42:13 +02:00
struct Buffer::BufferData *
2006-10-06 13:37:25 +02:00
Buffer::Allocate (uint32_t reqSize, uint32_t reqStart)
2006-08-29 17:42:13 +02:00
{
2006-09-05 13:18:11 +02:00
if (reqSize == 0) {
reqSize = 1;
}
assert (reqSize >= 1);
uint32_t size = reqSize - 1 + sizeof (struct Buffer::BufferData);
uint8_t *b = new uint8_t [size];
struct BufferData *data = reinterpret_cast<struct Buffer::BufferData*>(b);
data->m_size = reqSize;
data->m_initialStart = reqStart;
data->m_dirtyStart = reqStart;
data->m_dirtySize = 0;
data->m_count = 1;
return data;
2006-08-29 17:42:13 +02:00
}
void
2006-10-06 13:37:25 +02:00
Buffer::Deallocate (struct Buffer::BufferData *data)
2006-08-29 17:42:13 +02:00
{
2006-09-05 13:18:11 +02:00
uint8_t *buf = reinterpret_cast<uint8_t *> (data);
delete [] buf;
2006-08-29 17:42:13 +02:00
}
#ifdef USE_FREE_LIST
void
2006-10-06 13:37:25 +02:00
Buffer::Recycle (struct Buffer::BufferData *data)
2006-08-29 17:42:13 +02:00
{
2006-09-05 13:18:11 +02:00
assert (data->m_count == 0);
/* get rid of it if it is too small for later reuse. */
if (data->m_size < (Buffer::m_maxTotalAddStart + Buffer::m_maxTotalAddEnd)) {
2006-10-06 13:37:25 +02:00
Buffer::Deallocate (data);
2006-09-05 13:18:11 +02:00
return;
}
/* feed into free list */
if (Buffer::m_freeList.size () > 1000) {
2006-10-06 13:37:25 +02:00
Buffer::Deallocate (data);
2006-09-05 13:18:11 +02:00
} else {
Buffer::m_freeList.push_back (data);
}
2006-08-29 17:42:13 +02:00
}
Buffer::BufferData *
2006-10-06 13:37:25 +02:00
Buffer::Create (void)
2006-08-29 17:42:13 +02:00
{
2006-09-05 13:18:11 +02:00
/* try to find a buffer correctly sized. */
while (!Buffer::m_freeList.empty ()) {
struct Buffer::BufferData *data = Buffer::m_freeList.back ();
Buffer::m_freeList.pop_back ();
if (data->m_size >= (m_maxTotalAddStart + m_maxTotalAddEnd)) {
data->m_initialStart = m_maxTotalAddStart;
data->m_dirtyStart = m_maxTotalAddStart;
data->m_dirtySize = 0;
data->m_count = 1;
return data;
}
2006-10-06 13:37:25 +02:00
Buffer::Deallocate (data);
2006-09-05 13:18:11 +02:00
}
2006-10-06 13:37:25 +02:00
struct Buffer::BufferData *data = Buffer::Allocate (m_maxTotalAddStart+m_maxTotalAddEnd,
2006-09-05 13:18:11 +02:00
m_maxTotalAddStart);
assert (data->m_count == 1);
return data;
2006-08-29 17:42:13 +02:00
}
#else
void
2006-10-06 13:37:25 +02:00
Buffer::Recycle (struct Buffer::BufferData *data)
2006-08-29 17:42:13 +02:00
{
2006-10-06 13:37:25 +02:00
Buffer::Deallocate (data);
2006-08-29 17:42:13 +02:00
}
Buffer::BufferData *
2006-10-06 13:37:25 +02:00
Buffer::Create (void)
2006-08-29 17:42:13 +02:00
{
2006-10-06 13:37:25 +02:00
return Buffer::Allocate (m_maxTotalAddStart+m_maxTotalAddEnd,
m_maxTotalAddStart);
2006-08-29 17:42:13 +02:00
}
#endif
2006-08-29 17:55:34 +02:00
}; // namespace ns3
2006-08-29 17:42:13 +02:00
#include <cassert>
2006-08-29 17:55:34 +02:00
namespace ns3 {
2006-08-29 17:42:13 +02:00
void
2006-10-06 13:37:25 +02:00
Buffer::AddAtStart (uint32_t start)
2006-08-29 17:42:13 +02:00
{
2006-09-05 13:18:11 +02:00
assert (m_start <= m_data->m_initialStart);
bool isDirty = m_data->m_count > 1 && m_start > m_data->m_dirtyStart;
if (m_start >= start && !isDirty) {
/* enough space in the buffer and not dirty. */
m_start -= start;
m_size += start;
} else if (m_size + start <= m_data->m_size && !isDirty) {
/* enough space but need to move data around to fit new data */
2006-10-06 13:37:25 +02:00
memmove (m_data->m_data + start, GetStart (), m_size);
2006-09-05 13:18:11 +02:00
assert (start > m_start);
m_data->m_initialStart += start;
2006-10-06 13:37:25 +02:00
m_start = 0;
m_size += start;
2006-09-05 13:18:11 +02:00
} else if (m_start < start) {
/* not enough space in buffer */
uint32_t newSize = m_size + start;
2006-10-06 13:37:25 +02:00
struct Buffer::BufferData *newData = Buffer::Allocate (newSize, 0);
memcpy (newData->m_data + start, GetStart (), m_size);
2006-09-05 13:18:11 +02:00
newData->m_initialStart = m_data->m_initialStart + start;
m_data->m_count--;
if (m_data->m_count == 0) {
2006-10-06 13:37:25 +02:00
Buffer::Deallocate (m_data);
2006-09-05 13:18:11 +02:00
}
m_data = newData;
m_start = 0;
m_size = newSize;
} else {
/* enough space in the buffer but it is dirty ! */
assert (isDirty);
2006-10-06 13:37:25 +02:00
struct Buffer::BufferData *newData = Buffer::Create ();
memcpy (newData->m_data + m_start, GetStart (), m_size);
2006-09-05 13:18:11 +02:00
newData->m_initialStart = m_data->m_initialStart;
m_data->m_count--;
if (m_data->m_count == 0) {
2006-10-06 13:37:25 +02:00
Recycle (m_data);
2006-09-05 13:18:11 +02:00
}
m_data = newData;
m_start -= start;
m_size += start;
}
// update dirty area
m_data->m_dirtyStart = m_start;
m_data->m_dirtySize = m_size;
// update m_maxTotalAddStart
uint32_t addedAtStart;
if (m_data->m_initialStart > m_start) {
addedAtStart = m_data->m_initialStart - m_start;
} else {
addedAtStart = 0;
}
if (addedAtStart > m_maxTotalAddStart) {
m_maxTotalAddStart = addedAtStart;
}
TRACE ("start add="<<start<<", start="<<m_start<<", size="<<m_size<<", zero="<<m_zeroAreaSize<<
", real size="<<m_data->m_size<<", ini start="<<m_data->m_initialStart<<
", dirty start="<<m_data->m_dirtyStart<<", dirty size="<<m_data->m_dirtySize);
2006-08-29 17:42:13 +02:00
}
void
2006-10-06 13:37:25 +02:00
Buffer::AddAtEnd (uint32_t end)
2006-08-29 17:42:13 +02:00
{
2006-09-05 13:18:11 +02:00
assert (m_start <= m_data->m_initialStart);
bool isDirty = m_data->m_count > 1 &&
m_start + m_size < m_data->m_dirtyStart + m_data->m_dirtySize;
if (m_start + m_size + end <= m_data->m_size && !isDirty) {
/* enough space in buffer and not dirty */
m_size += end;
} else if (m_size + end <= m_data->m_size && !isDirty) {
/* enough space but need to move data around to fit the extra data */
2006-10-06 13:37:25 +02:00
uint32_t newStart = m_data->m_size - (m_size + end);
memmove (m_data->m_data + newStart, GetStart (), m_size);
2006-09-05 13:18:11 +02:00
assert (newStart < m_start);
m_data->m_initialStart -= m_start - newStart;
2006-10-06 13:37:25 +02:00
m_start = newStart;
m_size += end;
2006-09-05 13:18:11 +02:00
} else if (m_start + m_size + end > m_data->m_size) {
/* not enough space in buffer */
uint32_t newSize = m_size + end;
2006-10-06 13:37:25 +02:00
struct Buffer::BufferData *newData = Buffer::Allocate (newSize, 0);
memcpy (newData->m_data, GetStart (), m_size);
2006-09-05 13:18:11 +02:00
newData->m_initialStart = m_data->m_initialStart;
m_data->m_count--;
if (m_data->m_count == 0) {
2006-10-06 13:37:25 +02:00
Buffer::Deallocate (m_data);
2006-09-05 13:18:11 +02:00
}
m_data = newData;
m_size = newSize;
m_start = 0;
} else {
/* enough space in the buffer but it is dirty ! */
assert (isDirty);
2006-10-06 13:37:25 +02:00
struct Buffer::BufferData *newData = Buffer::Create ();
memcpy (newData->m_data + m_start, GetStart (), m_size);
2006-09-05 13:18:11 +02:00
newData->m_initialStart = m_data->m_initialStart;
m_data->m_count--;
if (m_data->m_count == 0) {
2006-10-06 13:37:25 +02:00
Recycle (m_data);
2006-09-05 13:18:11 +02:00
}
m_data = newData;
m_size += end;
}
// update dirty area
m_data->m_dirtyStart = m_start;
m_data->m_dirtySize = m_size;
// update m_maxTotalAddEnd
uint32_t endLoc = m_start + m_size;
uint32_t addedAtEnd;
if (m_data->m_initialStart < endLoc) {
addedAtEnd = endLoc - m_data->m_initialStart;
} else {
addedAtEnd = 0;
}
if (addedAtEnd > m_maxTotalAddEnd) {
m_maxTotalAddEnd = addedAtEnd;
}
TRACE ("end add="<<end<<", start="<<m_start<<", size="<<m_size<<", zero="<<m_zeroAreaSize<<
", real size="<<m_data->m_size<<", ini start="<<m_data->m_initialStart<<
", dirty start="<<m_data->m_dirtyStart<<", dirty size="<<m_data->m_dirtySize);
2006-08-29 17:42:13 +02:00
}
void
2006-10-06 13:37:25 +02:00
Buffer::RemoveAtStart (uint32_t start)
2006-08-29 17:42:13 +02:00
{
2006-09-05 13:18:11 +02:00
if (m_zeroAreaSize == 0) {
if (m_size <= start) {
m_start += m_size;
m_size = 0;
} else {
m_start += start;
m_size -= start;
}
} else {
assert (m_data->m_initialStart >= m_start);
uint32_t zeroStart = m_data->m_initialStart - m_start;
uint32_t zeroEnd = zeroStart + m_zeroAreaSize;
uint32_t dataEnd = m_size + m_zeroAreaSize;
if (start <= zeroStart) {
/* only remove start of buffer */
m_start += start;
m_size -= start;
} else if (start <= zeroEnd) {
/* remove start of buffer _and_ start of zero area */
m_start += zeroStart;
uint32_t zeroDelta = start - zeroStart;
m_zeroAreaSize -= zeroDelta;
assert (zeroDelta <= start);
m_size -= zeroStart;
} else if (start <= dataEnd) {
/* remove start of buffer, complete zero area, and part
* of end of buffer */
m_start += start - m_zeroAreaSize;
m_size -= start - m_zeroAreaSize;
m_zeroAreaSize = 0;
} else {
/* remove all buffer */
m_start += m_size;
m_size = 0;
m_zeroAreaSize = 0;
}
}
TRACE ("start remove="<<start<<", start="<<m_start<<", size="<<m_size<<", zero="<<m_zeroAreaSize<<
", real size="<<m_data->m_size<<", ini start="<<m_data->m_initialStart<<
", dirty start="<<m_data->m_dirtyStart<<", dirty size="<<m_data->m_dirtySize);
2006-08-29 17:42:13 +02:00
}
void
2006-10-06 13:37:25 +02:00
Buffer::RemoveAtEnd (uint32_t end)
2006-08-29 17:42:13 +02:00
{
2006-09-05 13:18:11 +02:00
if (m_zeroAreaSize == 0) {
if (m_size <= end) {
m_size = 0;
} else {
m_size -= end;
}
} else {
assert (m_data->m_initialStart >= m_start);
uint32_t zeroStart = m_data->m_initialStart - m_start;
uint32_t zeroEnd = zeroStart + m_zeroAreaSize;
uint32_t dataEnd = m_size + m_zeroAreaSize;
assert (zeroStart <= m_size);
assert (zeroEnd <= m_size + m_zeroAreaSize);
if (dataEnd <= end) {
/* remove all buffer */
m_zeroAreaSize = 0;
m_start += m_size;
m_size = 0;
} else if (dataEnd - zeroStart <= end) {
/* remove end of buffer, zero area, part of start of buffer */
assert (end >= m_zeroAreaSize);
m_size -= end - m_zeroAreaSize;
m_zeroAreaSize = 0;
} else if (dataEnd - zeroEnd <= end) {
/* remove end of buffer, part of zero area */
uint32_t zeroDelta = end - (dataEnd - zeroEnd);
m_zeroAreaSize -= zeroDelta;
m_size -= end - zeroDelta;
} else {
/* remove part of end of buffer */
m_size -= end;
}
}
TRACE ("end remove="<<end<<", start="<<m_start<<", size="<<m_size<<", zero="<<m_zeroAreaSize<<
", real size="<<m_data->m_size<<", ini start="<<m_data->m_initialStart<<
", dirty start="<<m_data->m_dirtyStart<<", dirty size="<<m_data->m_dirtySize);
2006-08-29 17:42:13 +02:00
}
Buffer
2006-10-06 13:37:25 +02:00
Buffer::CreateFragment (uint32_t start, uint32_t length) const
2006-08-29 17:42:13 +02:00
{
2006-09-05 13:18:11 +02:00
uint32_t zeroStart = m_data->m_initialStart - m_start;
uint32_t zeroEnd = zeroStart + m_zeroAreaSize;
if (m_zeroAreaSize != 0 &&
start + length > zeroStart &&
start <= zeroEnd) {
2006-10-06 13:37:25 +02:00
TransformIntoRealBuffer ();
2006-09-05 13:18:11 +02:00
}
Buffer tmp = *this;
2006-10-06 13:37:25 +02:00
tmp.RemoveAtStart (start);
tmp.RemoveAtEnd (GetSize () - (start + length));
2006-09-05 13:18:11 +02:00
return tmp;
2006-08-29 17:42:13 +02:00
}
void
2006-10-06 13:37:25 +02:00
Buffer::TransformIntoRealBuffer (void) const
2006-08-29 17:42:13 +02:00
{
2006-09-05 13:18:11 +02:00
if (m_zeroAreaSize != 0) {
assert (m_data->m_initialStart >= m_start);
assert (m_size >= (m_data->m_initialStart - m_start));
Buffer tmp;
2006-10-06 13:37:25 +02:00
tmp.AddAtStart (m_zeroAreaSize);
tmp.Begin ().WriteU8 (0, m_zeroAreaSize);
2006-09-05 13:18:11 +02:00
uint32_t dataStart = m_data->m_initialStart - m_start;
2006-10-06 13:37:25 +02:00
tmp.AddAtStart (dataStart);
tmp.Begin ().Write (m_data->m_data+m_start, dataStart);
2006-09-05 13:18:11 +02:00
uint32_t dataEnd = m_size - (m_data->m_initialStart - m_start);
2006-10-06 13:37:25 +02:00
tmp.AddAtEnd (dataEnd);
Buffer::Iterator i = tmp.End ();
i.Prev (dataEnd);
i.Write (m_data->m_data+m_data->m_initialStart,dataEnd);
2006-09-05 13:18:11 +02:00
*const_cast<Buffer *> (this) = tmp;
}
2006-08-29 17:42:13 +02:00
}
2006-09-08 18:45:48 +02:00
uint8_t const*
2006-10-06 13:37:25 +02:00
Buffer::PeekData (void) const
2006-08-29 17:42:13 +02:00
{
2006-10-06 13:37:25 +02:00
TransformIntoRealBuffer ();
2006-09-05 13:18:11 +02:00
return m_data->m_data + m_start;
2006-08-29 17:42:13 +02:00
}
2006-08-29 17:55:34 +02:00
}; // namespace ns3
2006-08-29 17:42:13 +02:00
#ifdef RUN_SELF_TESTS
2006-08-29 17:51:04 +02:00
#include "ns3/test.h"
2006-08-29 17:42:13 +02:00
#include <iomanip>
2006-08-29 17:55:34 +02:00
namespace ns3 {
2006-08-29 17:42:13 +02:00
class BufferTest: public Test {
private:
2006-10-06 13:37:25 +02:00
bool EnsureWrittenBytes (Buffer b, uint32_t n, uint8_t array[]);
2006-08-29 17:42:13 +02:00
public:
2006-10-06 13:37:25 +02:00
virtual bool RunTests (void);
BufferTest ();
2006-08-29 17:42:13 +02:00
};
BufferTest::BufferTest ()
2006-09-05 13:18:11 +02:00
: Test ("Buffer") {}
2006-08-29 17:42:13 +02:00
bool
2006-10-06 13:37:25 +02:00
BufferTest::EnsureWrittenBytes (Buffer b, uint32_t n, uint8_t array[])
2006-08-29 17:42:13 +02:00
{
2006-09-05 13:18:11 +02:00
bool success = true;
uint8_t *expected = array;
2006-09-08 18:45:48 +02:00
uint8_t const*got;
2006-10-06 13:37:25 +02:00
got = b.PeekData ();
2006-09-05 13:18:11 +02:00
for (uint32_t j = 0; j < n; j++) {
if (got[j] != expected[j]) {
success = false;
}
}
if (!success) {
2006-10-06 13:37:25 +02:00
Failure () << "Buffer -- ";
Failure () << "expected: n=";
Failure () << n << ", ";
Failure ().setf (std::ios::hex, std::ios::basefield);
2006-09-05 13:18:11 +02:00
for (uint32_t j = 0; j < n; j++) {
2006-10-06 13:37:25 +02:00
Failure () << (uint16_t)expected[j] << " ";
2006-09-05 13:18:11 +02:00
}
2006-10-06 13:37:25 +02:00
Failure ().setf (std::ios::dec, std::ios::basefield);
Failure () << "got: ";
Failure ().setf (std::ios::hex, std::ios::basefield);
2006-09-05 13:18:11 +02:00
for (uint32_t j = 0; j < n; j++) {
2006-10-06 13:37:25 +02:00
Failure () << (uint16_t)got[j] << " ";
2006-09-05 13:18:11 +02:00
}
2006-10-06 13:37:25 +02:00
Failure () << std::endl;
2006-09-05 13:18:11 +02:00
}
return success;
2006-08-29 17:42:13 +02:00
}
/* Note: works only when variadic macros are
* available which is the case for gcc.
* XXX
*/
#define ENSURE_WRITTEN_BYTES(buffer, n, ...) \
{ \
2006-09-05 13:18:11 +02:00
uint8_t bytes[] = {__VA_ARGS__}; \
2006-10-06 13:37:25 +02:00
if (!EnsureWrittenBytes (buffer, n , bytes)) { \
2006-09-05 13:18:11 +02:00
ok = false; \
} \
2006-08-29 17:42:13 +02:00
}
bool
2006-10-06 13:37:25 +02:00
BufferTest::RunTests (void)
2006-08-29 17:42:13 +02:00
{
2006-09-05 13:18:11 +02:00
bool ok = true;
Buffer buffer;
Buffer::Iterator i;
2006-10-06 13:37:25 +02:00
buffer.AddAtStart (6);
i = buffer.Begin ();
i.WriteU8 (0x66);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 1, 0x66);
2006-10-06 13:37:25 +02:00
i = buffer.Begin ();
i.WriteU8 (0x67);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 1, 0x67);
2006-10-06 13:37:25 +02:00
i.WriteHtonU16 (0x6568);
i = buffer.Begin ();
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 3, 0x67, 0x65, 0x68);
2006-10-06 13:37:25 +02:00
i.WriteHtonU16 (0x6369);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 3, 0x63, 0x69, 0x68);
2006-10-06 13:37:25 +02:00
i.WriteHtonU32 (0xdeadbeaf);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 6, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf);
2006-10-06 13:37:25 +02:00
buffer.AddAtStart (2);
i = buffer.Begin ();
i.WriteU16 (0);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 8, 0, 0, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf);
2006-10-06 13:37:25 +02:00
buffer.AddAtEnd (2);
i = buffer.Begin ();
i.Next (8);
i.WriteU16 (0);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 10, 0, 0, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
2006-10-06 13:37:25 +02:00
buffer.RemoveAtStart (3);
i = buffer.Begin ();
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 7, 0x69, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
2006-10-06 13:37:25 +02:00
buffer.RemoveAtEnd (4);
i = buffer.Begin ();
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 3, 0x69, 0xde, 0xad);
2006-10-06 13:37:25 +02:00
buffer.AddAtStart (1);
i = buffer.Begin ();
i.WriteU8 (0xff);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 4, 0xff, 0x69, 0xde, 0xad);
2006-10-06 13:37:25 +02:00
buffer.AddAtEnd (1);
i = buffer.Begin ();
i.Next (4);
i.WriteU8 (0xff);
i.Prev (2);
uint16_t saved = i.ReadU16 ();
i.Prev (2);
i.WriteHtonU16 (0xff00);
i.Prev (2);
if (i.ReadNtohU16 () != 0xff00) {
2006-09-05 13:18:11 +02:00
ok = false;
}
2006-10-06 13:37:25 +02:00
i.Prev (2);
i.WriteU16 (saved);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 5, 0xff, 0x69, 0xde, 0xad, 0xff);
Buffer o = buffer;
ENSURE_WRITTEN_BYTES (o, 5, 0xff, 0x69, 0xde, 0xad, 0xff);
2006-10-06 13:37:25 +02:00
o.AddAtStart (1);
i = o.Begin ();
i.WriteU8 (0xfe);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (o, 6, 0xfe, 0xff, 0x69, 0xde, 0xad, 0xff);
2006-10-06 13:37:25 +02:00
buffer.AddAtStart (2);
i = buffer.Begin ();
i.WriteU8 (0xfd);
i.WriteU8 (0xfd);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (o, 6, 0xfe, 0xff, 0x69, 0xde, 0xad, 0xff);
ENSURE_WRITTEN_BYTES (buffer, 7, 0xfd, 0xfd, 0xff, 0x69, 0xde, 0xad, 0xff);
// test self-assignment
{
Buffer a = o;
a = a;
}
2006-10-06 13:37:25 +02:00
// test Remove start.
2006-09-05 13:18:11 +02:00
buffer = Buffer (5);
ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0);
2006-10-06 13:37:25 +02:00
buffer.RemoveAtStart (1);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 4, 0, 0, 0, 0);
2006-10-06 13:37:25 +02:00
buffer.AddAtStart (1);
buffer.Begin ().WriteU8 (0xff);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 5, 0xff, 0, 0, 0, 0);
2006-10-06 13:37:25 +02:00
buffer.RemoveAtStart(3);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 2, 0, 0);
2006-10-06 13:37:25 +02:00
buffer.AddAtStart (4);
buffer.Begin ().WriteHtonU32 (0xdeadbeaf);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 6, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
2006-10-06 13:37:25 +02:00
buffer.RemoveAtStart (2);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 4, 0xbe, 0xaf, 0, 0);
2006-10-06 13:37:25 +02:00
buffer.AddAtEnd (4);
i = buffer.Begin ();
i.Next (4);
i.WriteHtonU32 (0xdeadbeaf);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 8, 0xbe, 0xaf, 0, 0, 0xde, 0xad, 0xbe, 0xaf);
2006-10-06 13:37:25 +02:00
buffer.RemoveAtStart (5);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 3, 0xad, 0xbe, 0xaf);
2006-10-06 13:37:25 +02:00
// test Remove end
2006-09-05 13:18:11 +02:00
buffer = Buffer (5);
ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0);
2006-10-06 13:37:25 +02:00
buffer.RemoveAtEnd (1);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 4, 0, 0, 0, 0);
2006-10-06 13:37:25 +02:00
buffer.AddAtEnd (2);
i = buffer.Begin ();
i.Next (4);
i.WriteU8 (0xab);
i.WriteU8 (0xac);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 6, 0, 0, 0, 0, 0xab, 0xac);
2006-10-06 13:37:25 +02:00
buffer.RemoveAtEnd (1);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0xab);
2006-10-06 13:37:25 +02:00
buffer.RemoveAtEnd (3);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 2, 0, 0);
2006-10-06 13:37:25 +02:00
buffer.AddAtEnd (6);
i = buffer.Begin ();
i.Next (2);
i.WriteU8 (0xac);
i.WriteU8 (0xad);
i.WriteU8 (0xae);
i.WriteU8 (0xaf);
i.WriteU8 (0xba);
i.WriteU8 (0xbb);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 8, 0, 0, 0xac, 0xad, 0xae, 0xaf, 0xba, 0xbb);
2006-10-06 13:37:25 +02:00
buffer.AddAtStart (3);
i = buffer.Begin ();
i.WriteU8 (0x30);
i.WriteU8 (0x31);
i.WriteU8 (0x32);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 11, 0x30, 0x31, 0x32, 0, 0, 0xac, 0xad, 0xae, 0xaf, 0xba, 0xbb);
2006-10-06 13:37:25 +02:00
buffer.RemoveAtEnd (9);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 2, 0x30, 0x31);
buffer = Buffer (3);
2006-10-06 13:37:25 +02:00
buffer.AddAtEnd (2);
i = buffer.Begin ();
i.Next (3);
i.WriteHtonU16 (0xabcd);
buffer.AddAtStart (1);
buffer.Begin ().WriteU8 (0x21);
2006-09-05 13:18:11 +02:00
ENSURE_WRITTEN_BYTES (buffer, 6, 0x21, 0, 0, 0, 0xab, 0xcd);
2006-10-06 13:37:25 +02:00
buffer.RemoveAtEnd (8);
if (buffer.GetSize () != 0) {
2006-09-05 13:18:11 +02:00
ok = false;
}
return ok;
2006-08-29 17:42:13 +02:00
}
static BufferTest gBufferTest;
2006-08-29 17:42:13 +02:00
2006-08-29 17:55:34 +02:00
}; // namespace ns3
2006-08-29 17:42:13 +02:00
#endif /* RUN_SELF_TESTS */