src/common/buffer.cc
author Nicola Baldo <nbaldo@cttc.es>
Thu Aug 13 09:36:16 2009 +0200 (2009-08-13)
changeset 4708 b251fb79becb
parent 4518 31f2881aa214
child 5261 7ccbdea36ec8
permissions -rw-r--r--
bug 639: Buffer::CopyData is buggy.
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     2 /*
     3  * Copyright (c) 2005,2006,2007 INRIA
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License version 2 as
     7  * published by the Free Software Foundation;
     8  *
     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.
    13  *
    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    17  *
    18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    19  */
    20 #include "buffer.h"
    21 #include "ns3/assert.h"
    22 #include "ns3/log.h"
    23 #include "ns3/fatal-error.h"
    24 #include <iostream>
    25 
    26 NS_LOG_COMPONENT_DEFINE ("Buffer");
    27 
    28 #define LOG_INTERNAL_STATE(y)                                                                    \
    29 NS_LOG_LOGIC (y << "start="<<m_start<<", end="<<m_end<<", zero start="<<m_zeroAreaStart<<              \
    30           ", zero end="<<m_zeroAreaEnd<<", count="<<m_data->m_count<<", size="<<m_data->m_size<<   \
    31           ", dirty start="<<m_data->m_dirtyStart<<", dirty end="<<m_data->m_dirtyEnd)
    32 
    33 #ifdef BUFFER_HEURISTICS
    34 #define HEURISTICS(x) x
    35 #else
    36 #define HEURISTICS(x)
    37 #endif
    38 
    39 //#define PRINT_STATS 1
    40 
    41 namespace ns3 {
    42 
    43 /**
    44  * This data structure is variable-sized through its last member whose size
    45  * is determined at allocation time and stored in the m_size field.
    46  *
    47  * The so-called "dirty area" describes the area in the buffer which
    48  * has been reserved and used by a user. Multiple Buffer instances
    49  * may reference the same BufferData object instance and may
    50  * reference different parts of the underlying byte buffer. The
    51  * "dirty area" is union of all the areas referenced by the Buffer
    52  * instances which reference the same BufferData instance.
    53  * New user data can be safely written only outside of the "dirty
    54  * area" if the reference count is higher than 1 (that is, if
    55  * more than one Buffer instance references the same BufferData).
    56  */
    57 struct BufferData {
    58   /* The reference count of an instance of this data structure.
    59    * Each buffer which references an instance holds a count.
    60    */
    61   uint32_t m_count;
    62   /* the size of the m_data field below.
    63    */
    64   uint32_t m_size;
    65   /* offset from the start of the m_data field below to the
    66    * start of the area in which user bytes were written.
    67    */
    68   uint32_t m_dirtyStart;
    69   /* offset from the start of the m_data field below to the
    70    * end of the area in which user bytes were written.
    71    */
    72   uint32_t m_dirtyEnd;
    73   /* The real data buffer holds _at least_ one byte.
    74    * Its real size is stored in the m_size field.
    75    */
    76   uint8_t m_data[1];
    77 };
    78 class BufferDataList : public std::vector<struct BufferData*>
    79 {
    80 public:
    81   ~BufferDataList ();
    82 };
    83 
    84 static struct BufferData *BufferAllocate (uint32_t reqSize);
    85 
    86 static void BufferDeallocate (struct BufferData *data);
    87 
    88 
    89 } // namespace ns3
    90 
    91 namespace ns3 {
    92 
    93 #ifdef BUFFER_HEURISTICS
    94 static uint32_t g_recommendedStart = 0;
    95 static uint64_t g_nAddNoRealloc = 0;
    96 static uint64_t g_nAddRealloc = 0;
    97 static BufferDataList  g_freeList;
    98 static uint32_t g_maxSize = 0;
    99 static uint64_t g_nAllocs = 0;
   100 static uint64_t g_nCreates = 0;
   101 #endif /* BUFFER_HEURISTICS */
   102 
   103 BufferDataList::~BufferDataList ()
   104 {
   105 #ifdef PRINT_STATS
   106 #ifdef BUFFER_HEURISTICS
   107   double efficiency;
   108   efficiency = g_nAllocs;
   109   efficiency /= g_nCreates;
   110   std::cout <<"buffer free list efficiency="<<efficiency<<" (lower is better)" << std::endl;
   111   std::cout <<"buffer free list max size="<<g_maxSize<<std::endl;
   112   std::cout <<"buffer free list recommended start="<<g_recommendedStart<<std::endl;
   113   double addEfficiency;
   114   addEfficiency = g_nAddRealloc;
   115   addEfficiency /= g_nAddNoRealloc;
   116   std::cout <<"buffer add efficiency=" << addEfficiency << " (lower is better)"<<std::endl;
   117   //std::cout <<"n add reallocs="<< g_nAddRealloc << std::endl;
   118   //std::cout <<"n add no reallocs="<< g_nAddNoRealloc << std::endl;
   119 #endif /* BUFFER_HEURISTICS */
   120 #endif /* PRINT_STATS */
   121   for (BufferDataList::iterator i = begin ();
   122        i != end (); i++)
   123     {
   124       BufferDeallocate (*i);
   125     }
   126 }
   127 
   128 struct BufferData *
   129 BufferAllocate (uint32_t reqSize)
   130 {
   131   if (reqSize == 0) 
   132     {
   133       reqSize = 1;
   134     }
   135   NS_ASSERT (reqSize >= 1);
   136   uint32_t size = reqSize - 1 + sizeof (struct BufferData);
   137   uint8_t *b = new uint8_t [size];
   138   struct BufferData *data = reinterpret_cast<struct BufferData*>(b);
   139   data->m_size = reqSize;
   140   data->m_count = 1;
   141   return data;
   142 }
   143 
   144 void
   145 BufferDeallocate (struct BufferData *data)
   146 {
   147   NS_ASSERT (data->m_count == 0);
   148   uint8_t *buf = reinterpret_cast<uint8_t *> (data);
   149   delete [] buf;
   150 }
   151 #ifdef BUFFER_HEURISTICS
   152 void
   153 Buffer::Recycle (struct BufferData *data)
   154 {
   155   NS_ASSERT (data->m_count == 0);
   156   g_maxSize = std::max (g_maxSize, data->m_size);
   157   /* feed into free list */
   158   if (data->m_size < g_maxSize ||
   159       g_freeList.size () > 1000)
   160     {
   161       BufferDeallocate (data);
   162     }
   163   else
   164     {
   165       g_freeList.push_back (data);
   166     }
   167 }
   168 
   169 BufferData *
   170 Buffer::Create (uint32_t dataSize)
   171 {
   172   /* try to find a buffer correctly sized. */
   173   g_nCreates++;
   174   while (!g_freeList.empty ()) 
   175     {
   176       struct BufferData *data = g_freeList.back ();
   177       g_freeList.pop_back ();
   178       if (data->m_size >= dataSize) 
   179         {
   180           data->m_count = 1;
   181           return data;
   182         }
   183       BufferDeallocate (data);
   184     }
   185   g_nAllocs++;
   186   struct BufferData *data = BufferAllocate (dataSize);
   187   NS_ASSERT (data->m_count == 1);
   188   return data;
   189 }
   190 #else
   191 void
   192 Buffer::Recycle (struct BufferData *data)
   193 {
   194   NS_ASSERT (data->m_count == 0);
   195   BufferDeallocate (data);
   196 }
   197 
   198 BufferData *
   199 Buffer::Create (uint32_t size)
   200 {
   201   return BufferAllocate (size);
   202 }
   203 #endif
   204 
   205 Buffer::Buffer ()
   206 {
   207   NS_LOG_FUNCTION (this);
   208   Initialize (0);
   209 }
   210 
   211 Buffer::Buffer (uint32_t dataSize)
   212 {
   213   NS_LOG_FUNCTION (this << dataSize);
   214   Initialize (dataSize);
   215 }
   216 
   217 bool
   218 Buffer::CheckInternalState (void) const
   219 {
   220   bool offsetsOk = 
   221     m_start <= m_zeroAreaStart &&
   222     m_zeroAreaStart <= m_zeroAreaEnd &&
   223     m_zeroAreaEnd <= m_end;
   224   bool dirtyOk =
   225     m_start >= m_data->m_dirtyStart &&
   226     m_end <= m_data->m_dirtyEnd;
   227   bool internalSizeOk = m_end - (m_zeroAreaEnd - m_zeroAreaStart) <= m_data->m_size &&
   228     m_start <= m_data->m_size &&
   229     m_zeroAreaStart <= m_data->m_size;
   230 
   231   bool ok = m_data->m_count > 0 && offsetsOk && dirtyOk && internalSizeOk;
   232   if (!ok)
   233     {
   234       LOG_INTERNAL_STATE ("check " << this << 
   235                           ", " << (offsetsOk?"true":"false") << 
   236                           ", " << (dirtyOk?"true":"false") << 
   237                           ", " << (internalSizeOk?"true":"false") << " ");
   238     }
   239   return ok;
   240 }
   241 
   242 void
   243 Buffer::Initialize (uint32_t zeroSize)
   244 {
   245   NS_LOG_FUNCTION (this << zeroSize);
   246   m_data = Buffer::Create (0);
   247 #ifdef BUFFER_HEURISTICS
   248   m_start = std::min (m_data->m_size, g_recommendedStart);
   249   m_maxZeroAreaStart = m_start;
   250 #else
   251   m_start = 0;
   252 #endif /* BUFFER_HEURISTICS */
   253   m_zeroAreaStart = m_start;
   254   m_zeroAreaEnd = m_zeroAreaStart + zeroSize;
   255   m_end = m_zeroAreaEnd;
   256   m_data->m_dirtyStart = m_start;
   257   m_data->m_dirtyEnd = m_end;
   258   NS_ASSERT (CheckInternalState ());
   259 }
   260 
   261 Buffer::Buffer (Buffer const&o)
   262   : m_data (o.m_data),
   263 #ifdef BUFFER_HEURISTICS
   264     m_maxZeroAreaStart (o.m_zeroAreaStart),
   265 #endif
   266     m_zeroAreaStart (o.m_zeroAreaStart),
   267     m_zeroAreaEnd (o.m_zeroAreaEnd),
   268     m_start (o.m_start),
   269     m_end (o.m_end)
   270 {
   271   NS_LOG_FUNCTION (this << &o);
   272   m_data->m_count++;
   273   NS_ASSERT (CheckInternalState ());
   274 }
   275 
   276 Buffer &
   277 Buffer::operator = (Buffer const&o)
   278 {
   279   NS_LOG_FUNCTION (this << &o);
   280   NS_ASSERT (CheckInternalState ());
   281   if (m_data != o.m_data) 
   282     {
   283       // not assignment to self.
   284       m_data->m_count--;
   285       if (m_data->m_count == 0) 
   286         {
   287           Recycle (m_data);
   288         }
   289       m_data = o.m_data;
   290       m_data->m_count++;
   291     }
   292   HEURISTICS (
   293   g_recommendedStart = std::max (g_recommendedStart, m_maxZeroAreaStart);
   294   m_maxZeroAreaStart = o.m_maxZeroAreaStart;
   295   );
   296   m_zeroAreaStart = o.m_zeroAreaStart;
   297   m_zeroAreaEnd = o.m_zeroAreaEnd;
   298   m_start = o.m_start;
   299   m_end = o.m_end;
   300   NS_ASSERT (CheckInternalState ());
   301   return *this;
   302 }
   303 
   304 Buffer::~Buffer ()
   305 {
   306   NS_LOG_FUNCTION (this);
   307   NS_ASSERT (CheckInternalState ());
   308   HEURISTICS (g_recommendedStart = std::max (g_recommendedStart, m_maxZeroAreaStart));
   309   m_data->m_count--;
   310   if (m_data->m_count == 0) 
   311     {
   312       Recycle (m_data);
   313     }
   314 }
   315 
   316 uint32_t 
   317 Buffer::GetSize (void) const
   318 {
   319   NS_ASSERT (CheckInternalState ());
   320   return m_end - m_start;
   321 }
   322 
   323 Buffer::Iterator 
   324 Buffer::Begin (void) const
   325 {
   326   NS_ASSERT (CheckInternalState ());
   327   return Buffer::Iterator (this);
   328 }
   329 Buffer::Iterator 
   330 Buffer::End (void) const
   331 {
   332   NS_ASSERT (CheckInternalState ());
   333   return Buffer::Iterator (this, false);
   334 }
   335 
   336 uint32_t
   337 Buffer::GetInternalSize (void) const
   338 {
   339   return m_zeroAreaStart - m_start + m_end - m_zeroAreaEnd;
   340 }
   341 uint32_t
   342 Buffer::GetInternalEnd (void) const
   343 {
   344   return m_end - (m_zeroAreaEnd - m_zeroAreaStart);
   345 }
   346 
   347 bool
   348 Buffer::AddAtStart (uint32_t start)
   349 {
   350   NS_LOG_FUNCTION (this << start);
   351   bool dirty;
   352   NS_ASSERT (CheckInternalState ());
   353   bool isDirty = m_data->m_count > 1 && m_start > m_data->m_dirtyStart;
   354   if (m_start >= start && !isDirty)
   355     {
   356       /* enough space in the buffer and not dirty. 
   357        * To add: |..|
   358        * Before: |*****---------***|
   359        * After:  |***..---------***|
   360        */
   361       NS_ASSERT (m_data->m_count == 1 || m_start == m_data->m_dirtyStart);
   362       m_start -= start;
   363       dirty = m_start > m_data->m_dirtyStart;
   364       // update dirty area
   365       m_data->m_dirtyStart = m_start;
   366       HEURISTICS (g_nAddNoRealloc++);
   367     } 
   368   else
   369     {
   370       uint32_t newSize = GetInternalSize () + start;
   371       struct BufferData *newData = Buffer::Create (newSize);
   372       memcpy (newData->m_data + start, m_data->m_data + m_start, GetInternalSize ());
   373       m_data->m_count--;
   374       if (m_data->m_count == 0)
   375         {
   376           Buffer::Recycle (m_data);
   377         }
   378       m_data = newData;
   379 
   380       int32_t delta = start - m_start;
   381       m_start += delta;
   382       m_zeroAreaStart += delta;
   383       m_zeroAreaEnd += delta;
   384       m_end += delta;
   385       m_start -= start;
   386 
   387       // update dirty area
   388       m_data->m_dirtyStart = m_start;
   389       m_data->m_dirtyEnd = m_end;
   390 
   391       dirty = true;
   392 
   393       HEURISTICS (g_nAddRealloc++);
   394     }
   395   HEURISTICS (m_maxZeroAreaStart = std::max (m_maxZeroAreaStart, m_zeroAreaStart));
   396   LOG_INTERNAL_STATE ("add start=" << start << ", ");
   397   NS_ASSERT (CheckInternalState ());
   398   return dirty;
   399 }
   400 bool
   401 Buffer::AddAtEnd (uint32_t end)
   402 {
   403   NS_LOG_FUNCTION (this << end);
   404   bool dirty;
   405   NS_ASSERT (CheckInternalState ());
   406   bool isDirty = m_data->m_count > 1 && m_end < m_data->m_dirtyEnd;
   407   if (GetInternalEnd () + end <= m_data->m_size && !isDirty)
   408     {
   409       /* enough space in buffer and not dirty
   410        * Add:    |...|
   411        * Before: |**----*****|
   412        * After:  |**----...**|
   413        */
   414       NS_ASSERT (m_data->m_count == 1 || m_end == m_data->m_dirtyEnd);
   415       m_end += end;
   416       // update dirty area.
   417       m_data->m_dirtyEnd = m_end;
   418 
   419       dirty = m_end < m_data->m_dirtyEnd;
   420 
   421       HEURISTICS (g_nAddNoRealloc++);
   422     } 
   423   else
   424     {
   425       uint32_t newSize = GetInternalSize () + end;
   426       struct BufferData *newData = Buffer::Create (newSize);
   427       memcpy (newData->m_data, m_data->m_data + m_start, GetInternalSize ());
   428       m_data->m_count--;
   429       if (m_data->m_count == 0) 
   430         {
   431           Buffer::Recycle (m_data);
   432         }
   433       m_data = newData;
   434 
   435       int32_t delta = -m_start;
   436       m_zeroAreaStart += delta;
   437       m_zeroAreaEnd += delta;
   438       m_end += delta;
   439       m_start += delta;
   440       m_end += end;
   441 
   442       // update dirty area
   443       m_data->m_dirtyStart = m_start;
   444       m_data->m_dirtyEnd = m_end;
   445 
   446       dirty = true;
   447 
   448       HEURISTICS (g_nAddRealloc++);
   449     } 
   450   HEURISTICS (m_maxZeroAreaStart = std::max (m_maxZeroAreaStart, m_zeroAreaStart));
   451   LOG_INTERNAL_STATE ("add end=" << end << ", ");
   452   NS_ASSERT (CheckInternalState ());
   453 
   454   return dirty;
   455 }
   456 
   457 void
   458 Buffer::AddAtEnd (const Buffer &o)
   459 {
   460   NS_LOG_FUNCTION (this << &o);
   461   if (m_data->m_count == 1 &&
   462       m_end == m_zeroAreaEnd &&
   463       m_end == m_data->m_dirtyEnd &&
   464       o.m_start == o.m_zeroAreaStart &&
   465       o.m_zeroAreaEnd - o.m_zeroAreaStart > 0)
   466     {
   467       /**
   468        * This is an optimization which kicks in when
   469        * we attempt to aggregate two buffers which contain
   470        * adjacent zero areas.
   471        */
   472       uint32_t zeroSize = o.m_zeroAreaEnd - o.m_zeroAreaStart;
   473       m_zeroAreaEnd += zeroSize;
   474       m_end = m_zeroAreaEnd;
   475       m_data->m_dirtyEnd = m_zeroAreaEnd;
   476       uint32_t endData = o.m_end - o.m_zeroAreaEnd;
   477       AddAtEnd (endData);
   478       Buffer::Iterator dst = End ();
   479       dst.Prev (endData);
   480       Buffer::Iterator src = o.End ();
   481       src.Prev (endData);
   482       dst.Write (src, o.End ());
   483       NS_ASSERT (CheckInternalState ());
   484       return;
   485     }
   486 
   487   Buffer dst = CreateFullCopy ();
   488   Buffer src = o.CreateFullCopy ();
   489 
   490   dst.AddAtEnd (src.GetSize ());
   491   Buffer::Iterator destStart = dst.End ();
   492   destStart.Prev (src.GetSize ());
   493   destStart.Write (src.Begin (), src.End ());
   494   *this = dst;
   495   NS_ASSERT (CheckInternalState ());
   496 }
   497 
   498 void 
   499 Buffer::RemoveAtStart (uint32_t start)
   500 {
   501   NS_LOG_FUNCTION (this << start);
   502   NS_ASSERT (CheckInternalState ());
   503   uint32_t newStart = m_start + start;
   504   if (newStart <= m_zeroAreaStart)
   505     {
   506       /* only remove start of buffer 
   507        */
   508       m_start = newStart;
   509     }
   510   else if (newStart <= m_zeroAreaEnd)
   511     {
   512       /* remove start of buffer _and_ start of zero area
   513        */
   514       uint32_t delta = newStart - m_zeroAreaStart;
   515       m_start = m_zeroAreaStart;
   516       m_zeroAreaEnd -= delta;
   517       m_end -= delta;
   518     } 
   519   else if (newStart <= m_end)
   520     {
   521       /* remove start of buffer, complete zero area, and part
   522        * of end of buffer 
   523        */
   524       NS_ASSERT (m_end >= start);
   525       uint32_t zeroSize = m_zeroAreaEnd - m_zeroAreaStart;
   526       m_start = newStart - zeroSize;
   527       m_end -= zeroSize;
   528       m_zeroAreaStart = m_start;
   529       m_zeroAreaEnd = m_start;
   530     }
   531   else 
   532     {
   533       /* remove all buffer */
   534       m_end -= m_zeroAreaEnd - m_zeroAreaStart;
   535       m_start = m_end;
   536       m_zeroAreaEnd = m_end;
   537       m_zeroAreaStart = m_end;
   538     }
   539   HEURISTICS (m_maxZeroAreaStart = std::max (m_maxZeroAreaStart, m_zeroAreaStart));
   540   LOG_INTERNAL_STATE ("rem start=" << start << ", ");
   541   NS_ASSERT (CheckInternalState ());
   542 }
   543 void 
   544 Buffer::RemoveAtEnd (uint32_t end)
   545 {
   546   NS_LOG_FUNCTION (this << end);
   547   NS_ASSERT (CheckInternalState ());
   548   uint32_t newEnd = m_end - std::min (end, m_end - m_start);
   549   if (newEnd > m_zeroAreaEnd)
   550     {
   551       /* remove part of end of buffer */
   552       m_end = newEnd;
   553     }
   554   else if (newEnd > m_zeroAreaStart)
   555     {
   556       /* remove end of buffer, part of zero area */
   557       m_end = newEnd;
   558       m_zeroAreaEnd = newEnd;
   559     }
   560   else if (newEnd > m_start)
   561     {
   562       /* remove end of buffer, zero area, part of start of buffer */
   563       m_end = newEnd;
   564       m_zeroAreaEnd = newEnd;
   565       m_zeroAreaStart = newEnd;
   566     }
   567   else
   568     {
   569       /* remove all buffer */
   570       m_end = m_start;
   571       m_zeroAreaEnd = m_start;
   572       m_zeroAreaStart = m_start;
   573     }
   574   HEURISTICS (m_maxZeroAreaStart = std::max (m_maxZeroAreaStart, m_zeroAreaStart));
   575   LOG_INTERNAL_STATE ("rem end=" << end << ", ");
   576   NS_ASSERT (CheckInternalState ());
   577 }
   578 
   579 Buffer 
   580 Buffer::CreateFragment (uint32_t start, uint32_t length) const
   581 {
   582   NS_LOG_FUNCTION (this << start << length);
   583   NS_ASSERT (CheckInternalState ());
   584   Buffer tmp = *this;
   585   tmp.RemoveAtStart (start);
   586   tmp.RemoveAtEnd (GetSize () - (start + length));
   587   NS_ASSERT (CheckInternalState ());
   588   return tmp;
   589 }
   590 
   591 Buffer 
   592 Buffer::CreateFullCopy (void) const
   593 {
   594   NS_LOG_FUNCTION (this);
   595   NS_ASSERT (CheckInternalState ());
   596   if (m_zeroAreaEnd - m_zeroAreaStart != 0) 
   597     {
   598       Buffer tmp;
   599       tmp.AddAtStart (m_zeroAreaEnd - m_zeroAreaStart);
   600       tmp.Begin ().WriteU8 (0, m_zeroAreaEnd - m_zeroAreaStart);
   601       uint32_t dataStart = m_zeroAreaStart - m_start;
   602       tmp.AddAtStart (dataStart);
   603       tmp.Begin ().Write (m_data->m_data+m_start, dataStart);
   604       uint32_t dataEnd = m_end - m_zeroAreaEnd;
   605       tmp.AddAtEnd (dataEnd);
   606       Buffer::Iterator i = tmp.End ();
   607       i.Prev (dataEnd);
   608       i.Write (m_data->m_data+m_zeroAreaStart,dataEnd);
   609       NS_ASSERT (tmp.CheckInternalState ());
   610       return tmp;
   611     }
   612   NS_ASSERT (CheckInternalState ());
   613   return *this;
   614 }
   615 
   616 int32_t 
   617 Buffer::GetCurrentStartOffset (void) const
   618 {
   619   return m_start;
   620 }
   621 int32_t 
   622 Buffer::GetCurrentEndOffset (void) const
   623 {
   624   return m_end;
   625 }
   626 
   627 
   628 void
   629 Buffer::TransformIntoRealBuffer (void) const
   630 {
   631   NS_ASSERT (CheckInternalState ());
   632   Buffer tmp = CreateFullCopy ();
   633   *const_cast<Buffer *> (this) = tmp;
   634   NS_ASSERT (CheckInternalState ());
   635 }
   636 
   637 
   638 uint8_t const*
   639 Buffer::PeekData (void) const
   640 {
   641   NS_ASSERT (CheckInternalState ());
   642   TransformIntoRealBuffer ();
   643   NS_ASSERT (CheckInternalState ());
   644   return m_data->m_data + m_start;
   645 }
   646 
   647 void
   648 Buffer::CopyData(std::ostream *os, uint32_t size) const
   649 {
   650   if (size > 0)
   651     {
   652       uint32_t tmpsize = std::min (m_zeroAreaStart-m_start, size);
   653       os->write((const char*)(m_data->m_data + m_start), tmpsize);
   654       if (size > tmpsize) 
   655         { 
   656           size -= m_zeroAreaStart-m_start;
   657           tmpsize = std::min (m_zeroAreaEnd - m_zeroAreaStart, size);
   658           char zero = 0;
   659           for (uint32_t i = 0; i < tmpsize; ++i)
   660             {
   661               os->write (&zero, 1);
   662             }
   663           if (size > tmpsize)
   664             {
   665               size -= tmpsize;
   666               tmpsize = std::min (m_end - m_zeroAreaEnd, size);
   667               os->write ((const char*)(m_data->m_data + m_zeroAreaStart), tmpsize); 
   668             }
   669         }
   670     }
   671 }
   672 
   673 /******************************************************
   674  *            The buffer iterator below.
   675  ******************************************************/
   676 
   677 
   678 Buffer::Iterator::Iterator ()
   679   : m_zeroStart (0),
   680     m_zeroEnd (0),
   681     m_dataStart (0),
   682     m_dataEnd (0),
   683     m_current (0),
   684     m_data (0)
   685 {}
   686 Buffer::Iterator::Iterator (Buffer const*buffer)
   687 {
   688   Construct (buffer);
   689   m_current = m_dataStart;
   690 }
   691 Buffer::Iterator::Iterator (Buffer const*buffer, bool dummy)
   692 {
   693   Construct (buffer);
   694   m_current = m_dataEnd;
   695 }
   696 
   697 void
   698 Buffer::Iterator::Construct (const Buffer *buffer)
   699 {
   700   m_zeroStart = buffer->m_zeroAreaStart;
   701   m_zeroEnd = buffer->m_zeroAreaEnd;
   702   m_dataStart = buffer->m_start;
   703   m_dataEnd = buffer->m_end;
   704   m_data = buffer->m_data->m_data;
   705 }
   706 
   707 void 
   708 Buffer::Iterator::Next (void)
   709 {
   710   NS_ASSERT (m_current + 1 <= m_dataEnd);
   711   m_current++;
   712 }
   713 void 
   714 Buffer::Iterator::Prev (void)
   715 {
   716   NS_ASSERT (m_current >= 1);
   717   m_current--;
   718 }
   719 void 
   720 Buffer::Iterator::Next (uint32_t delta)
   721 {
   722   NS_ASSERT (m_current + delta <= m_dataEnd);
   723   m_current += delta;
   724 }
   725 void 
   726 Buffer::Iterator::Prev (uint32_t delta)
   727 {
   728   NS_ASSERT (m_current >= delta);
   729   m_current -= delta;
   730 }
   731 uint32_t
   732 Buffer::Iterator::GetDistanceFrom (Iterator const &o) const
   733 {
   734   NS_ASSERT (m_data == o.m_data);
   735   int32_t diff = m_current - o.m_current;
   736   if (diff < 0)
   737     {
   738       return -diff;
   739     }
   740   else
   741     {
   742       return diff;
   743     }
   744 }
   745 
   746 bool 
   747 Buffer::Iterator::IsEnd (void) const
   748 {
   749   return m_current == m_dataEnd;
   750 }
   751 bool 
   752 Buffer::Iterator::IsStart (void) const
   753 {
   754   return m_current == m_dataStart;
   755 }
   756 
   757 bool 
   758 Buffer::Iterator::CheckNoZero (uint32_t start, uint32_t end) const
   759 {
   760   bool ok = true;
   761   for (uint32_t i = start; i < end; i++)
   762     {
   763       if (!Check (i))
   764         {
   765           ok = false;
   766         }
   767     }
   768   return ok;
   769 }
   770 bool 
   771 Buffer::Iterator::Check (uint32_t i) const
   772 {
   773   return i >= m_dataStart && 
   774     !(i >= m_zeroStart && i < m_zeroEnd) &&
   775     i <= m_dataEnd;
   776 }
   777 
   778 
   779 void 
   780 Buffer::Iterator::Write (Iterator start, Iterator end)
   781 {
   782   NS_ASSERT (start.m_data == end.m_data);
   783   NS_ASSERT (start.m_current <= end.m_current);
   784   NS_ASSERT (start.m_zeroStart == end.m_zeroStart);
   785   NS_ASSERT (start.m_zeroEnd == end.m_zeroEnd);
   786   NS_ASSERT (m_data != start.m_data);
   787   uint32_t size = end.m_current - start.m_current;
   788   Iterator cur = start;
   789   for (uint32_t i = 0; i < size; i++)
   790     {
   791       uint8_t data = cur.ReadU8 ();
   792       WriteU8 (data);
   793     }
   794 }
   795 
   796 void 
   797 Buffer::Iterator::WriteU16 (uint16_t data)
   798 {
   799   WriteU8 (data & 0xff);
   800   data >>= 8;
   801   WriteU8 (data & 0xff);
   802 }
   803 void 
   804 Buffer::Iterator::WriteU32 (uint32_t data)
   805 {
   806   WriteU8 (data & 0xff);
   807   data >>= 8;
   808   WriteU8 (data & 0xff);
   809   data >>= 8;
   810   WriteU8 (data & 0xff);
   811   data >>= 8;
   812   WriteU8 (data & 0xff);
   813 }
   814 void 
   815 Buffer::Iterator::WriteU64 (uint64_t data)
   816 {
   817   WriteU8 (data & 0xff);
   818   data >>= 8;
   819   WriteU8 (data & 0xff);
   820   data >>= 8;
   821   WriteU8 (data & 0xff);
   822   data >>= 8;
   823   WriteU8 (data & 0xff);
   824   data >>= 8;
   825   WriteU8 (data & 0xff);
   826   data >>= 8;
   827   WriteU8 (data & 0xff);
   828   data >>= 8;
   829   WriteU8 (data & 0xff);
   830   data >>= 8;
   831   WriteU8 (data & 0xff);
   832 }
   833 void 
   834 Buffer::Iterator::WriteHtolsbU16 (uint16_t data)
   835 {
   836   WriteU8 ((data >> 0) & 0xff);
   837   WriteU8 ((data >> 8) & 0xff);
   838 }
   839 void 
   840 Buffer::Iterator::WriteHtolsbU32 (uint32_t data)
   841 {
   842   WriteU8 ((data >> 0) & 0xff);
   843   WriteU8 ((data >> 8) & 0xff);
   844   WriteU8 ((data >> 16) & 0xff);
   845   WriteU8 ((data >> 24) & 0xff);
   846 }
   847 void 
   848 Buffer::Iterator::WriteHtolsbU64 (uint64_t data)
   849 {
   850   WriteU8 ((data >> 0) & 0xff);
   851   WriteU8 ((data >> 8) & 0xff);
   852   WriteU8 ((data >> 16) & 0xff);
   853   WriteU8 ((data >> 24) & 0xff);
   854   WriteU8 ((data >> 32) & 0xff);
   855   WriteU8 ((data >> 40) & 0xff);
   856   WriteU8 ((data >> 48) & 0xff);
   857   WriteU8 ((data >> 56) & 0xff);
   858 }
   859 
   860 void 
   861 Buffer::Iterator::WriteHtonU16 (uint16_t data)
   862 {
   863   WriteU8 ((data >> 8) & 0xff);
   864   WriteU8 ((data >> 0) & 0xff);
   865 }
   866 void 
   867 Buffer::Iterator::WriteHtonU32 (uint32_t data)
   868 {
   869   WriteU8 ((data >> 24) & 0xff);
   870   WriteU8 ((data >> 16) & 0xff);
   871   WriteU8 ((data >> 8) & 0xff);
   872   WriteU8 ((data >> 0) & 0xff);
   873 }
   874 void 
   875 Buffer::Iterator::WriteHtonU64 (uint64_t data)
   876 {
   877   WriteU8 ((data >> 56) & 0xff);
   878   WriteU8 ((data >> 48) & 0xff);
   879   WriteU8 ((data >> 40) & 0xff);
   880   WriteU8 ((data >> 32) & 0xff);
   881   WriteU8 ((data >> 24) & 0xff);
   882   WriteU8 ((data >> 16) & 0xff);
   883   WriteU8 ((data >> 8) & 0xff);
   884   WriteU8 ((data >> 0) & 0xff);
   885 }
   886 void 
   887 Buffer::Iterator::Write (uint8_t const*buffer, uint32_t size)
   888 {
   889   for (uint32_t i = 0; i < size; i++)
   890     {
   891       WriteU8 (buffer[i]);
   892     }
   893 }
   894 
   895 uint16_t 
   896 Buffer::Iterator::ReadU16 (void)
   897 {
   898   uint8_t byte0 = ReadU8 ();
   899   uint8_t byte1 = ReadU8 ();
   900   uint16_t data = byte1;
   901   data <<= 8;
   902   data |= byte0;
   903 
   904   return data;
   905 }
   906 uint32_t 
   907 Buffer::Iterator::ReadU32 (void)
   908 {
   909   uint8_t byte0 = ReadU8 ();
   910   uint8_t byte1 = ReadU8 ();
   911   uint8_t byte2 = ReadU8 ();
   912   uint8_t byte3 = ReadU8 ();
   913   uint32_t data = byte3;
   914   data <<= 8;
   915   data |= byte2;
   916   data <<= 8;
   917   data |= byte1;
   918   data <<= 8;
   919   data |= byte0;
   920   return data;
   921 }
   922 uint64_t 
   923 Buffer::Iterator::ReadU64 (void)
   924 {
   925   uint8_t byte0 = ReadU8 ();
   926   uint8_t byte1 = ReadU8 ();
   927   uint8_t byte2 = ReadU8 ();
   928   uint8_t byte3 = ReadU8 ();
   929   uint8_t byte4 = ReadU8 ();
   930   uint8_t byte5 = ReadU8 ();
   931   uint8_t byte6 = ReadU8 ();
   932   uint8_t byte7 = ReadU8 ();
   933   uint64_t data = byte7;
   934   data <<= 8;
   935   data |= byte6;
   936   data <<= 8;
   937   data |= byte5;
   938   data <<= 8;
   939   data |= byte4;
   940   data <<= 8;
   941   data |= byte3;
   942   data <<= 8;
   943   data |= byte2;
   944   data <<= 8;
   945   data |= byte1;
   946   data <<= 8;
   947   data |= byte0;
   948 
   949   return data;
   950 }
   951 uint16_t 
   952 Buffer::Iterator::ReadNtohU16 (void)
   953 {
   954   uint16_t retval = 0;
   955   retval |= ReadU8 ();
   956   retval <<= 8;
   957   retval |= ReadU8 ();
   958   return retval;
   959 }
   960 uint32_t 
   961 Buffer::Iterator::ReadNtohU32 (void)
   962 {
   963   uint32_t retval = 0;
   964   retval |= ReadU8 ();
   965   retval <<= 8;
   966   retval |= ReadU8 ();
   967   retval <<= 8;
   968   retval |= ReadU8 ();
   969   retval <<= 8;
   970   retval |= ReadU8 ();
   971   return retval;
   972 }
   973 uint64_t 
   974 Buffer::Iterator::ReadNtohU64 (void)
   975 {
   976   uint64_t retval = 0;
   977   retval |= ReadU8 ();
   978   retval <<= 8;
   979   retval |= ReadU8 ();
   980   retval <<= 8;
   981   retval |= ReadU8 ();
   982   retval <<= 8;
   983   retval |= ReadU8 ();
   984   retval <<= 8;
   985   retval |= ReadU8 ();
   986   retval <<= 8;
   987   retval |= ReadU8 ();
   988   retval <<= 8;
   989   retval |= ReadU8 ();
   990   retval <<= 8;
   991   retval |= ReadU8 ();
   992   return retval;
   993 }
   994 uint16_t 
   995 Buffer::Iterator::ReadLsbtohU16 (void)
   996 {
   997   uint8_t byte0 = ReadU8 ();
   998   uint8_t byte1 = ReadU8 ();
   999   uint16_t data = byte1;
  1000   data <<= 8;
  1001   data |= byte0;
  1002   return data;
  1003 }
  1004 uint32_t 
  1005 Buffer::Iterator::ReadLsbtohU32 (void)
  1006 {
  1007   uint8_t byte0 = ReadU8 ();
  1008   uint8_t byte1 = ReadU8 ();
  1009   uint8_t byte2 = ReadU8 ();
  1010   uint8_t byte3 = ReadU8 ();
  1011   uint32_t data = byte3;
  1012   data <<= 8;
  1013   data |= byte2;
  1014   data <<= 8;
  1015   data |= byte1;
  1016   data <<= 8;
  1017   data |= byte0;
  1018   return data;
  1019 }
  1020 uint64_t 
  1021 Buffer::Iterator::ReadLsbtohU64 (void)
  1022 {
  1023   uint8_t byte0 = ReadU8 ();
  1024   uint8_t byte1 = ReadU8 ();
  1025   uint8_t byte2 = ReadU8 ();
  1026   uint8_t byte3 = ReadU8 ();
  1027   uint8_t byte4 = ReadU8 ();
  1028   uint8_t byte5 = ReadU8 ();
  1029   uint8_t byte6 = ReadU8 ();
  1030   uint8_t byte7 = ReadU8 ();
  1031   uint64_t data = byte7;
  1032   data <<= 8;
  1033   data |= byte6;
  1034   data <<= 8;
  1035   data |= byte5;
  1036   data <<= 8;
  1037   data |= byte4;
  1038   data <<= 8;
  1039   data |= byte3;
  1040   data <<= 8;
  1041   data |= byte2;
  1042   data <<= 8;
  1043   data |= byte1;
  1044   data <<= 8;
  1045   data |= byte0;
  1046 
  1047   return data;
  1048 }
  1049 void 
  1050 Buffer::Iterator::Read (uint8_t *buffer, uint32_t size)
  1051 {
  1052   for (uint32_t i = 0; i < size; i++)
  1053     {
  1054       buffer[i] = ReadU8 ();
  1055     }
  1056 }
  1057 
  1058 #ifndef BUFFER_USE_INLINE
  1059 
  1060 void 
  1061 Buffer::Iterator::WriteU8  (uint8_t  data)
  1062 {
  1063   if (m_current < m_dataStart)
  1064     {
  1065       // XXX trying to write outside of data area
  1066       NS_ASSERT (false);
  1067     }
  1068   else if (m_current < m_zeroStart)
  1069     {
  1070       m_data[m_current] = data;
  1071       m_current++;
  1072     }
  1073   else if (m_current < m_zeroEnd)
  1074     {
  1075       // XXX trying to write in zero area
  1076       NS_ASSERT (false);
  1077     }
  1078   else if (m_current < m_dataEnd)
  1079     {
  1080       m_data[m_current - (m_zeroEnd-m_zeroStart)] = data;
  1081       m_current++;      
  1082     }
  1083   else 
  1084     {
  1085       // XXX trying to write outside of data area
  1086       NS_ASSERT (false);
  1087     }
  1088 }
  1089 
  1090 void 
  1091 Buffer::Iterator::WriteU8 (uint8_t  data, uint32_t len)
  1092 {
  1093   for (uint32_t i = 0; i < len; i++)
  1094     {
  1095       WriteU8 (data);
  1096     }
  1097 }
  1098 
  1099 uint8_t  
  1100 Buffer::Iterator::ReadU8 (void)
  1101 {
  1102   if (m_current < m_dataStart)
  1103     {
  1104       // XXX trying to read from outside of data area
  1105       NS_ASSERT (false);
  1106     }
  1107   else if (m_current < m_zeroStart)
  1108     {
  1109       uint8_t data = m_data[m_current];
  1110       m_current++;
  1111       return data;
  1112     }
  1113   else if (m_current < m_zeroEnd)
  1114     {
  1115       m_current++;
  1116       return 0;
  1117     }
  1118   else if (m_current < m_dataEnd)
  1119     {
  1120       uint8_t data = m_data[m_current - (m_zeroEnd-m_zeroStart)];
  1121       m_current++;
  1122       return data;
  1123     }
  1124   else 
  1125     {
  1126       // XXX trying to read from outside of data area
  1127       NS_ASSERT (false);
  1128     }
  1129   // to quiet compiler.
  1130   return 0;
  1131 }
  1132 
  1133 #endif /* BUFFER_USE_INLINE */
  1134 
  1135 uint16_t
  1136 Buffer::Iterator::CalculateIpChecksum(uint16_t size)
  1137 {
  1138   return CalculateIpChecksum(size, 0);
  1139 }
  1140 
  1141 uint16_t
  1142 Buffer::Iterator::CalculateIpChecksum(uint16_t size, uint32_t initialChecksum)
  1143 {
  1144   /* see RFC 1071 to understand this code. */
  1145   uint32_t sum = initialChecksum;
  1146 
  1147   for (int j = 0; j < size/2; j++)
  1148     sum += ReadU16 ();
  1149 
  1150   if (size & 1)
  1151      sum += ReadU8 ();
  1152 
  1153   while (sum >> 16)
  1154     sum = (sum & 0xffff) + (sum >> 16);
  1155   return ~sum;
  1156 }
  1157 
  1158 uint32_t 
  1159 Buffer::Iterator::GetSize (void) const
  1160 {
  1161   return m_dataEnd - m_dataStart;
  1162 }
  1163 
  1164 } // namespace ns3
  1165 
  1166 
  1167 #ifdef RUN_SELF_TESTS
  1168 
  1169 #include "ns3/test.h"
  1170 #include "ns3/random-variable.h"
  1171 #include <iomanip>
  1172 
  1173 
  1174 namespace ns3 {
  1175 
  1176 class BufferTest: public Test {
  1177 private:
  1178   bool EnsureWrittenBytes (Buffer b, uint32_t n, uint8_t array[]);
  1179 public:
  1180   virtual bool RunTests (void);
  1181   BufferTest ();
  1182 };
  1183 
  1184 
  1185 BufferTest::BufferTest ()
  1186   : Test ("Buffer") {}
  1187 
  1188 bool
  1189 BufferTest::EnsureWrittenBytes (Buffer b, uint32_t n, uint8_t array[])
  1190 {
  1191   bool success = true;
  1192   uint8_t *expected = array;
  1193   uint8_t const*got;
  1194   got = b.PeekData ();
  1195   for (uint32_t j = 0; j < n; j++) 
  1196     {
  1197       if (got[j] != expected[j]) 
  1198         {
  1199           success = false;
  1200         }
  1201     }
  1202   if (!success) 
  1203     {
  1204       Failure () << "Buffer -- ";
  1205       Failure () << "expected: n=";
  1206       Failure () << n << ", ";
  1207       Failure ().setf (std::ios::hex, std::ios::basefield);
  1208       for (uint32_t j = 0; j < n; j++) 
  1209         {
  1210           Failure () << (uint16_t)expected[j] << " ";
  1211         }
  1212       Failure ().setf (std::ios::dec, std::ios::basefield);
  1213       Failure () << "got: ";
  1214       Failure ().setf (std::ios::hex, std::ios::basefield);
  1215       for (uint32_t j = 0; j < n; j++) 
  1216         {
  1217           Failure () << (uint16_t)got[j] << " ";
  1218         }
  1219       Failure () << std::endl;
  1220     }
  1221   return success;
  1222 }
  1223 
  1224 /* Note: works only when variadic macros are
  1225  * available which is the case for gcc.
  1226  * XXX
  1227  */
  1228 #define ENSURE_WRITTEN_BYTES(buffer, n, ...)     \
  1229   {                                              \
  1230   uint8_t bytes[] = {__VA_ARGS__};             \
  1231   if (!EnsureWrittenBytes (buffer, n , bytes)) \
  1232     {                                          \
  1233       result = false;                          \
  1234     }                                          \
  1235   }
  1236 
  1237 bool
  1238 BufferTest::RunTests (void)
  1239 {
  1240   bool result = true;
  1241   Buffer buffer;
  1242   Buffer::Iterator i;
  1243   buffer.AddAtStart (6);
  1244   i = buffer.Begin ();
  1245   i.WriteU8 (0x66);
  1246   ENSURE_WRITTEN_BYTES (buffer, 1, 0x66);
  1247   i = buffer.Begin ();
  1248   i.WriteU8 (0x67);
  1249   ENSURE_WRITTEN_BYTES (buffer, 1, 0x67);
  1250   i.WriteHtonU16 (0x6568);
  1251   i = buffer.Begin ();
  1252   ENSURE_WRITTEN_BYTES (buffer, 3, 0x67, 0x65, 0x68);
  1253   i.WriteHtonU16 (0x6369);
  1254   ENSURE_WRITTEN_BYTES (buffer, 3, 0x63, 0x69, 0x68);
  1255   i.WriteHtonU32 (0xdeadbeaf);
  1256   ENSURE_WRITTEN_BYTES (buffer, 6, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf);
  1257   buffer.AddAtStart (2);
  1258   i = buffer.Begin ();
  1259   i.WriteU16 (0);
  1260   ENSURE_WRITTEN_BYTES (buffer, 8, 0, 0, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf);
  1261   buffer.AddAtEnd (2);
  1262   i = buffer.Begin ();
  1263   i.Next (8);
  1264   i.WriteU16 (0);
  1265   ENSURE_WRITTEN_BYTES (buffer, 10, 0, 0, 0x63, 0x69, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
  1266   buffer.RemoveAtStart (3);
  1267   i = buffer.Begin ();
  1268   ENSURE_WRITTEN_BYTES (buffer, 7, 0x69, 0xde, 0xad, 0xbe, 0xaf, 0, 0);
  1269   buffer.RemoveAtEnd (4);
  1270   i = buffer.Begin ();
  1271   ENSURE_WRITTEN_BYTES (buffer, 3, 0x69, 0xde, 0xad);
  1272   buffer.AddAtStart (1);
  1273   i = buffer.Begin ();
  1274   i.WriteU8 (0xff);
  1275   ENSURE_WRITTEN_BYTES (buffer, 4, 0xff, 0x69, 0xde, 0xad);
  1276   buffer.AddAtEnd (1);
  1277   i = buffer.Begin ();
  1278   i.Next (4);
  1279   i.WriteU8 (0xff);
  1280   i.Prev (2);
  1281   uint16_t saved = i.ReadU16 ();
  1282   i.Prev (2);
  1283   i.WriteHtonU16 (0xff00);
  1284   i.Prev (2);
  1285   if (i.ReadNtohU16 () != 0xff00) 
  1286     {
  1287       result = false;
  1288     }
  1289   i.Prev (2);
  1290   i.WriteU16 (saved);
  1291   ENSURE_WRITTEN_BYTES (buffer, 5, 0xff, 0x69, 0xde, 0xad, 0xff);
  1292   Buffer o = buffer;
  1293   ENSURE_WRITTEN_BYTES (o, 5, 0xff, 0x69, 0xde, 0xad, 0xff);
  1294   o.AddAtStart (1);
  1295   i = o.Begin ();
  1296   i.WriteU8 (0xfe);
  1297   ENSURE_WRITTEN_BYTES (o, 6, 0xfe, 0xff, 0x69, 0xde, 0xad, 0xff);
  1298   buffer.AddAtStart (2);
  1299   i = buffer.Begin ();
  1300   i.WriteU8 (0xfd);
  1301   i.WriteU8 (0xfd);
  1302   ENSURE_WRITTEN_BYTES (o, 6, 0xfe, 0xff, 0x69, 0xde, 0xad, 0xff);
  1303   ENSURE_WRITTEN_BYTES (buffer, 7, 0xfd, 0xfd, 0xff, 0x69, 0xde, 0xad, 0xff);
  1304 
  1305   // test 64-bit read/write
  1306   Buffer buff64;
  1307   buff64.AddAtStart(8);
  1308   i = buff64.Begin();
  1309   i.WriteU64 (0x0123456789ABCDEFllu);
  1310   ENSURE_WRITTEN_BYTES (buff64, 8, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01);
  1311   i = buff64.Begin();
  1312   if (i.ReadLsbtohU64() != 0x0123456789abcdefllu)
  1313     {
  1314        result = false;
  1315     }
  1316   i = buff64.Begin();
  1317   i.WriteHtolsbU64 (0x0123456789ABCDEFllu);
  1318   ENSURE_WRITTEN_BYTES (buff64, 8, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01);
  1319   i = buff64.Begin();
  1320   if (i.ReadLsbtohU64() != 0x0123456789abcdefllu)
  1321     {
  1322        result = false;
  1323     }
  1324   i = buff64.Begin();
  1325   i.WriteHtonU64 (0x0123456789ABCDEFllu);
  1326   ENSURE_WRITTEN_BYTES (buff64, 8, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef);
  1327   i = buff64.Begin();
  1328   if (i.ReadNtohU64() != 0x0123456789abcdefllu)
  1329     {
  1330        result = false;
  1331     }
  1332 
  1333   // test self-assignment
  1334   {
  1335       Buffer a = o;
  1336       a = a;
  1337   }
  1338 
  1339   // test Remove start.
  1340   buffer = Buffer (5);
  1341   ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0);
  1342   buffer.RemoveAtStart (1);
  1343   ENSURE_WRITTEN_BYTES (buffer, 4, 0, 0, 0, 0);
  1344   buffer.AddAtStart (1);
  1345   buffer.Begin ().WriteU8 (0xff);
  1346   ENSURE_WRITTEN_BYTES (buffer, 5, 0xff, 0, 0, 0, 0);
  1347   buffer.RemoveAtStart(3);
  1348   ENSURE_WRITTEN_BYTES (buffer, 2, 0, 0);
  1349   buffer.AddAtStart (4);
  1350   buffer.Begin ().WriteHtonU32 (0xdeadbeaf);
  1351   ENSURE_WRITTEN_BYTES (buffer, 6,  0xde, 0xad, 0xbe, 0xaf, 0, 0);
  1352   buffer.RemoveAtStart (2);
  1353   ENSURE_WRITTEN_BYTES (buffer, 4,  0xbe, 0xaf, 0, 0);
  1354   buffer.AddAtEnd (4);
  1355   i = buffer.Begin ();
  1356   i.Next (4);
  1357   i.WriteHtonU32 (0xdeadbeaf);
  1358   ENSURE_WRITTEN_BYTES (buffer, 8,  0xbe, 0xaf, 0, 0, 0xde, 0xad, 0xbe, 0xaf);
  1359   buffer.RemoveAtStart (5);
  1360   ENSURE_WRITTEN_BYTES (buffer, 3,  0xad, 0xbe, 0xaf);
  1361   // test Remove end
  1362   buffer = Buffer (5);
  1363   ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0);
  1364   buffer.RemoveAtEnd (1);
  1365   ENSURE_WRITTEN_BYTES (buffer, 4, 0, 0, 0, 0);
  1366   buffer.AddAtEnd (2);
  1367   i = buffer.Begin ();
  1368   i.Next (4);
  1369   i.WriteU8 (0xab);
  1370   i.WriteU8 (0xac);
  1371   ENSURE_WRITTEN_BYTES (buffer, 6, 0, 0, 0, 0, 0xab, 0xac);
  1372   buffer.RemoveAtEnd (1);
  1373   ENSURE_WRITTEN_BYTES (buffer, 5, 0, 0, 0, 0, 0xab);
  1374   buffer.RemoveAtEnd (3);
  1375   ENSURE_WRITTEN_BYTES (buffer, 2, 0, 0);
  1376   buffer.AddAtEnd (6);
  1377   i = buffer.Begin ();
  1378   i.Next (2);
  1379   i.WriteU8 (0xac);
  1380   i.WriteU8 (0xad);
  1381   i.WriteU8 (0xae);
  1382   i.WriteU8 (0xaf);
  1383   i.WriteU8 (0xba);
  1384   i.WriteU8 (0xbb);
  1385   ENSURE_WRITTEN_BYTES (buffer, 8, 0, 0, 0xac, 0xad, 0xae, 0xaf, 0xba, 0xbb);
  1386   buffer.AddAtStart (3);
  1387   i = buffer.Begin ();
  1388   i.WriteU8 (0x30);
  1389   i.WriteU8 (0x31);
  1390   i.WriteU8 (0x32);
  1391   ENSURE_WRITTEN_BYTES (buffer, 11, 0x30, 0x31, 0x32, 0, 0, 0xac, 0xad, 0xae, 0xaf, 0xba, 0xbb);
  1392   buffer.RemoveAtEnd (9);
  1393   ENSURE_WRITTEN_BYTES (buffer, 2, 0x30, 0x31);
  1394   buffer = Buffer (3);
  1395   buffer.AddAtEnd (2);
  1396   i = buffer.Begin ();
  1397   i.Next (3);
  1398   i.WriteHtonU16 (0xabcd);
  1399   buffer.AddAtStart (1);
  1400   buffer.Begin ().WriteU8 (0x21);
  1401   ENSURE_WRITTEN_BYTES (buffer, 6, 0x21, 0, 0, 0, 0xab, 0xcd);
  1402   buffer.RemoveAtEnd (8);
  1403   if (buffer.GetSize () != 0) 
  1404     {
  1405       result = false;
  1406     }
  1407 
  1408   buffer = Buffer (6);
  1409   buffer.AddAtStart (9);
  1410   buffer.AddAtEnd (3);
  1411   i = buffer.End ();
  1412   i.Prev (1);
  1413   i.WriteU8 (1, 1);
  1414 
  1415   buffer = Buffer (6);
  1416   buffer.AddAtStart (3);
  1417   buffer.RemoveAtEnd (8);
  1418   buffer.AddAtEnd (4);
  1419   i = buffer.End ();
  1420   i.Prev (4);
  1421   i.WriteU8 (1, 4);
  1422 
  1423   buffer = Buffer (1);
  1424   buffer.AddAtEnd (100);
  1425   i = buffer.End ();
  1426   i.Prev (100);
  1427   i.WriteU8 (1, 100);
  1428 
  1429 #if 0
  1430   buffer = Buffer (10);  
  1431   ENSURE_WRITTEN_BYTES (buffer, 10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
  1432   buffer.Begin ().WriteU8 (1);
  1433   ENSURE_WRITTEN_BYTES (buffer, 10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
  1434 #endif
  1435 
  1436   // Bug #54
  1437   {
  1438     const uint32_t actualSize = 72602;
  1439     const uint32_t chunkSize = 67624;
  1440     UniformVariable bytesRng (0, 256);
  1441 
  1442     Buffer inputBuffer;
  1443     Buffer outputBuffer;
  1444     
  1445     inputBuffer.AddAtEnd (actualSize);
  1446     {
  1447       Buffer::Iterator iter = inputBuffer.Begin ();
  1448       for (uint32_t i = 0; i < actualSize; i++)
  1449         iter.WriteU8 (static_cast<uint8_t> (bytesRng.GetValue ()));
  1450     }
  1451 
  1452     outputBuffer.AddAtEnd (chunkSize);
  1453     Buffer::Iterator iter = outputBuffer.End ();
  1454     iter.Prev (chunkSize);
  1455     iter.Write (inputBuffer.PeekData (), chunkSize);
  1456 
  1457     NS_TEST_ASSERT (memcmp (inputBuffer.PeekData (), outputBuffer.PeekData (), chunkSize) == 0);
  1458   }
  1459 
  1460   buffer = Buffer (5);
  1461   buffer.AddAtEnd (2);
  1462   i = buffer.End ();
  1463   i.Prev (2);
  1464   i.WriteU8 (0);
  1465   i.WriteU8 (0x66);
  1466   ENSURE_WRITTEN_BYTES (buffer, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66);
  1467   Buffer frag0 = buffer.CreateFragment (0, 2);
  1468   ENSURE_WRITTEN_BYTES (frag0, 2, 0x00, 0x00);
  1469   Buffer frag1 = buffer.CreateFragment (2, 5);
  1470   ENSURE_WRITTEN_BYTES (frag1, 5, 0x00, 0x00, 0x00, 0x00, 0x66);
  1471   frag0.AddAtEnd (frag1);
  1472   ENSURE_WRITTEN_BYTES (buffer, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66);
  1473   ENSURE_WRITTEN_BYTES (frag0, 7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66);
  1474 
  1475   return result;
  1476 }
  1477 
  1478 
  1479 
  1480 static BufferTest gBufferTest;
  1481 
  1482 } // namespace ns3
  1483 
  1484 #endif /* RUN_SELF_TESTS */
  1485 
  1486