A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
buffer.cc
Go to the documentation of this file.
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 
24 NS_LOG_COMPONENT_DEFINE ("Buffer");
25 
26 #define LOG_INTERNAL_STATE(y) \
27  NS_LOG_LOGIC (y << "start="<<m_start<<", end="<<m_end<<", zero start="<<m_zeroAreaStart<< \
28  ", zero end="<<m_zeroAreaEnd<<", count="<<m_data->m_count<<", size="<<m_data->m_size<< \
29  ", dirty start="<<m_data->m_dirtyStart<<", dirty end="<<m_data->m_dirtyEnd)
30 
31 namespace {
32 
33 static struct Zeroes
34 {
35  Zeroes ()
36  : size (1000)
37  {
38  memset (buffer, 0, size);
39  }
40  char buffer[1000];
41  const uint32_t size;
42 } g_zeroes;
43 
44 }
45 
46 namespace ns3 {
47 
48 
49 uint32_t Buffer::g_recommendedStart = 0;
50 #ifdef BUFFER_FREE_LIST
51 /* The following macros are pretty evil but they are needed to allow us to
52  * keep track of 3 possible states for the g_freeList variable:
53  * - uninitialized means that no one has created a buffer yet
54  * so no one has created the associated free list (it is created
55  * on-demand when the first buffer is created)
56  * - initialized means that the free list exists and is valid
57  * - destroyed means that the static destructors of this compilation unit
58  * have run so, the free list has been cleared from its content
59  * The key is that in destroyed state, we are careful not re-create it
60  * which is a typical weakness of lazy evaluation schemes which use
61  * '0' as a special value to indicate both un-initialized and destroyed.
62  * Note that it is important to use '0' as the marker for un-initialized state
63  * because the variable holding this state information is initialized to zero
64  * which the compiler assigns to zero-memory which is initialized to _zero_
65  * before the constructors run so this ensures perfect handling of crazy
66  * constructor orderings.
67  */
68 #define MAGIC_DESTROYED (~(long) 0)
69 #define IS_UNINITIALIZED(x) (x == (Buffer::FreeList*)0)
70 #define IS_DESTROYED(x) (x == (Buffer::FreeList*)MAGIC_DESTROYED)
71 #define IS_INITIALIZED(x) (!IS_UNINITIALIZED (x) && !IS_DESTROYED (x))
72 #define DESTROYED ((Buffer::FreeList*)MAGIC_DESTROYED)
73 #define UNINITIALIZED ((Buffer::FreeList*)0)
74 uint32_t Buffer::g_maxSize = 0;
75 Buffer::FreeList *Buffer::g_freeList = 0;
76 struct Buffer::LocalStaticDestructor Buffer::g_localStaticDestructor;
77 
78 Buffer::LocalStaticDestructor::~LocalStaticDestructor(void)
79 {
80  if (IS_INITIALIZED (g_freeList))
81  {
82  for (Buffer::FreeList::iterator i = g_freeList->begin ();
83  i != g_freeList->end (); i++)
84  {
85  Buffer::Deallocate (*i);
86  }
87  delete g_freeList;
88  g_freeList = DESTROYED;
89  }
90 }
91 
92 void
93 Buffer::Recycle (struct Buffer::Data *data)
94 {
95  NS_ASSERT (data->m_count == 0);
96  NS_ASSERT (!IS_UNINITIALIZED (g_freeList));
97  g_maxSize = std::max (g_maxSize, data->m_size);
98  /* feed into free list */
99  if (data->m_size < g_maxSize ||
100  IS_DESTROYED (g_freeList) ||
101  g_freeList->size () > 1000)
102  {
103  Buffer::Deallocate (data);
104  }
105  else
106  {
107  NS_ASSERT (IS_INITIALIZED (g_freeList));
108  g_freeList->push_back (data);
109  }
110 }
111 
112 Buffer::Data *
113 Buffer::Create (uint32_t dataSize)
114 {
115  /* try to find a buffer correctly sized. */
116  if (IS_UNINITIALIZED (g_freeList))
117  {
118  g_freeList = new Buffer::FreeList ();
119  }
120  else if (IS_INITIALIZED (g_freeList))
121  {
122  while (!g_freeList->empty ())
123  {
124  struct Buffer::Data *data = g_freeList->back ();
125  g_freeList->pop_back ();
126  if (data->m_size >= dataSize)
127  {
128  data->m_count = 1;
129  return data;
130  }
131  Buffer::Deallocate (data);
132  }
133  }
134  struct Buffer::Data *data = Buffer::Allocate (dataSize);
135  NS_ASSERT (data->m_count == 1);
136  return data;
137 }
138 #else /* BUFFER_FREE_LIST */
139 void
141 {
142  NS_ASSERT (data->m_count == 0);
143  Deallocate (data);
144 }
145 
146 Buffer::Data *
147 Buffer::Create (uint32_t size)
148 {
149  return Allocate (size);
150 }
151 #endif /* BUFFER_FREE_LIST */
152 
153 struct Buffer::Data *
154 Buffer::Allocate (uint32_t reqSize)
155 {
156  if (reqSize == 0)
157  {
158  reqSize = 1;
159  }
160  NS_ASSERT (reqSize >= 1);
161  uint32_t size = reqSize - 1 + sizeof (struct Buffer::Data);
162  uint8_t *b = new uint8_t [size];
163  struct Buffer::Data *data = reinterpret_cast<struct Buffer::Data*>(b);
164  data->m_size = reqSize;
165  data->m_count = 1;
166  return data;
167 }
168 
169 void
171 {
172  NS_ASSERT (data->m_count == 0);
173  uint8_t *buf = reinterpret_cast<uint8_t *> (data);
174  delete [] buf;
175 }
176 
178 {
179  NS_LOG_FUNCTION (this);
180  Initialize (0);
181 }
182 
183 Buffer::Buffer (uint32_t dataSize)
184 {
185  NS_LOG_FUNCTION (this << dataSize);
186  Initialize (dataSize);
187 }
188 
189 Buffer::Buffer (uint32_t dataSize, bool initialize)
190 {
191  NS_LOG_FUNCTION (this << dataSize << initialize);
192  if (initialize == true)
193  {
194  Initialize (dataSize);
195  }
196 }
197 
198 bool
200 {
201 #if 0
202  // If you want to modify any code in this file, enable this checking code.
203  // Otherwise, there is not much point is enabling it because the
204  // current implementation has been fairly seriously tested and the cost
205  // of this constant checking is pretty high, even for a debug build.
206  bool offsetsOk =
209  m_zeroAreaEnd <= m_end;
210  bool dirtyOk =
212  m_end <= m_data->m_dirtyEnd;
213  bool internalSizeOk = m_end - (m_zeroAreaEnd - m_zeroAreaStart) <= m_data->m_size &&
214  m_start <= m_data->m_size &&
215  m_zeroAreaStart <= m_data->m_size;
216 
217  bool ok = m_data->m_count > 0 && offsetsOk && dirtyOk && internalSizeOk;
218  if (!ok)
219  {
220  LOG_INTERNAL_STATE ("check " << this <<
221  ", " << (offsetsOk ? "true" : "false") <<
222  ", " << (dirtyOk ? "true" : "false") <<
223  ", " << (internalSizeOk ? "true" : "false") << " ");
224  }
225  return ok;
226 #else
227  return true;
228 #endif
229 }
230 
231 void
232 Buffer::Initialize (uint32_t zeroSize)
233 {
234  NS_LOG_FUNCTION (this << zeroSize);
235  m_data = Buffer::Create (0);
236  m_start = std::min (m_data->m_size, g_recommendedStart);
239  m_zeroAreaEnd = m_zeroAreaStart + zeroSize;
244 }
245 
246 Buffer &
247 Buffer::operator = (Buffer const&o)
248 {
249  NS_LOG_FUNCTION (this << &o);
251  if (m_data != o.m_data)
252  {
253  // not assignment to self.
254  m_data->m_count--;
255  if (m_data->m_count == 0)
256  {
257  Recycle (m_data);
258  }
259  m_data = o.m_data;
260  m_data->m_count++;
261  }
266  m_start = o.m_start;
267  m_end = o.m_end;
269  return *this;
270 }
271 
273 {
274  NS_LOG_FUNCTION (this);
277  m_data->m_count--;
278  if (m_data->m_count == 0)
279  {
280  Recycle (m_data);
281  }
282 }
283 
284 uint32_t
286 {
288 }
289 uint32_t
291 {
292  return m_end - (m_zeroAreaEnd - m_zeroAreaStart);
293 }
294 
295 bool
297 {
298  NS_LOG_FUNCTION (this << start);
299  bool dirty;
301  bool isDirty = m_data->m_count > 1 && m_start > m_data->m_dirtyStart;
302  if (m_start >= start && !isDirty)
303  {
304  /* enough space in the buffer and not dirty.
305  * To add: |..|
306  * Before: |*****---------***|
307  * After: |***..---------***|
308  */
310  m_start -= start;
311  dirty = m_start > m_data->m_dirtyStart;
312  // update dirty area
314  }
315  else
316  {
317  uint32_t newSize = GetInternalSize () + start;
318  struct Buffer::Data *newData = Buffer::Create (newSize);
319  memcpy (newData->m_data + start, m_data->m_data + m_start, GetInternalSize ());
320  m_data->m_count--;
321  if (m_data->m_count == 0)
322  {
324  }
325  m_data = newData;
326 
327  int32_t delta = start - m_start;
328  m_start += delta;
329  m_zeroAreaStart += delta;
330  m_zeroAreaEnd += delta;
331  m_end += delta;
332  m_start -= start;
333 
334  // update dirty area
337 
338  dirty = true;
339 
340  }
342  LOG_INTERNAL_STATE ("add start=" << start << ", ");
344  return dirty;
345 }
346 bool
347 Buffer::AddAtEnd (uint32_t end)
348 {
349  NS_LOG_FUNCTION (this << end);
350  bool dirty;
352  bool isDirty = m_data->m_count > 1 && m_end < m_data->m_dirtyEnd;
353  if (GetInternalEnd () + end <= m_data->m_size && !isDirty)
354  {
355  /* enough space in buffer and not dirty
356  * Add: |...|
357  * Before: |**----*****|
358  * After: |**----...**|
359  */
361  m_end += end;
362  // update dirty area.
364 
365  dirty = m_end < m_data->m_dirtyEnd;
366 
367  }
368  else
369  {
370  uint32_t newSize = GetInternalSize () + end;
371  struct Buffer::Data *newData = Buffer::Create (newSize);
372  memcpy (newData->m_data, m_data->m_data + m_start, GetInternalSize ());
373  m_data->m_count--;
374  if (m_data->m_count == 0)
375  {
377  }
378  m_data = newData;
379 
380  int32_t delta = -m_start;
381  m_zeroAreaStart += delta;
382  m_zeroAreaEnd += delta;
383  m_end += delta;
384  m_start += delta;
385  m_end += end;
386 
387  // update dirty area
390 
391  dirty = true;
392 
393  }
395  LOG_INTERNAL_STATE ("add end=" << end << ", ");
397 
398  return dirty;
399 }
400 
401 void
402 Buffer::AddAtEnd (const Buffer &o)
403 {
404  NS_LOG_FUNCTION (this << &o);
405  if (m_data->m_count == 1 &&
406  m_end == m_zeroAreaEnd &&
407  m_end == m_data->m_dirtyEnd &&
408  o.m_start == o.m_zeroAreaStart &&
409  o.m_zeroAreaEnd - o.m_zeroAreaStart > 0)
410  {
416  uint32_t zeroSize = o.m_zeroAreaEnd - o.m_zeroAreaStart;
417  m_zeroAreaEnd += zeroSize;
420  uint32_t endData = o.m_end - o.m_zeroAreaEnd;
421  AddAtEnd (endData);
422  Buffer::Iterator dst = End ();
423  dst.Prev (endData);
424  Buffer::Iterator src = o.End ();
425  src.Prev (endData);
426  dst.Write (src, o.End ());
428  return;
429  }
430 
431  Buffer dst = CreateFullCopy ();
432  Buffer src = o.CreateFullCopy ();
433 
434  dst.AddAtEnd (src.GetSize ());
435  Buffer::Iterator destStart = dst.End ();
436  destStart.Prev (src.GetSize ());
437  destStart.Write (src.Begin (), src.End ());
438  *this = dst;
440 }
441 
442 void
444 {
445  NS_LOG_FUNCTION (this << start);
447  uint32_t newStart = m_start + start;
448  if (newStart <= m_zeroAreaStart)
449  {
450  /* only remove start of buffer
451  */
452  m_start = newStart;
453  }
454  else if (newStart <= m_zeroAreaEnd)
455  {
456  /* remove start of buffer _and_ start of zero area
457  */
458  uint32_t delta = newStart - m_zeroAreaStart;
460  m_zeroAreaEnd -= delta;
461  m_end -= delta;
462  }
463  else if (newStart <= m_end)
464  {
465  /* remove start of buffer, complete zero area, and part
466  * of end of buffer
467  */
468  NS_ASSERT (m_end >= start);
469  uint32_t zeroSize = m_zeroAreaEnd - m_zeroAreaStart;
470  m_start = newStart - zeroSize;
471  m_end -= zeroSize;
472  m_zeroAreaStart = m_start;
474  }
475  else
476  {
477  /* remove all buffer */
479  m_start = m_end;
481  m_zeroAreaStart = m_end;
482  }
484  LOG_INTERNAL_STATE ("rem start=" << start << ", ");
486 }
487 void
488 Buffer::RemoveAtEnd (uint32_t end)
489 {
490  NS_LOG_FUNCTION (this << end);
492  uint32_t newEnd = m_end - std::min (end, m_end - m_start);
493  if (newEnd > m_zeroAreaEnd)
494  {
495  /* remove part of end of buffer */
496  m_end = newEnd;
497  }
498  else if (newEnd > m_zeroAreaStart)
499  {
500  /* remove end of buffer, part of zero area */
501  m_end = newEnd;
502  m_zeroAreaEnd = newEnd;
503  }
504  else if (newEnd > m_start)
505  {
506  /* remove end of buffer, zero area, part of start of buffer */
507  m_end = newEnd;
508  m_zeroAreaEnd = newEnd;
509  m_zeroAreaStart = newEnd;
510  }
511  else
512  {
513  /* remove all buffer */
514  m_end = m_start;
517  }
519  LOG_INTERNAL_STATE ("rem end=" << end << ", ");
521 }
522 
523 Buffer
524 Buffer::CreateFragment (uint32_t start, uint32_t length) const
525 {
526  NS_LOG_FUNCTION (this << start << length);
528  Buffer tmp = *this;
529  tmp.RemoveAtStart (start);
530  tmp.RemoveAtEnd (GetSize () - (start + length));
532  return tmp;
533 }
534 
535 Buffer
537 {
538  NS_LOG_FUNCTION (this);
540  if (m_zeroAreaEnd - m_zeroAreaStart != 0)
541  {
542  Buffer tmp;
545  uint32_t dataStart = m_zeroAreaStart - m_start;
546  tmp.AddAtStart (dataStart);
547  tmp.Begin ().Write (m_data->m_data+m_start, dataStart);
548  uint32_t dataEnd = m_end - m_zeroAreaEnd;
549  tmp.AddAtEnd (dataEnd);
550  Buffer::Iterator i = tmp.End ();
551  i.Prev (dataEnd);
552  i.Write (m_data->m_data+m_zeroAreaStart,dataEnd);
553  NS_ASSERT (tmp.CheckInternalState ());
554  return tmp;
555  }
557  return *this;
558 }
559 
560 uint32_t
562 {
563  uint32_t dataStart = (m_zeroAreaStart - m_start + 3) & (~0x3);
564  uint32_t dataEnd = (m_end - m_zeroAreaEnd + 3) & (~0x3);
565 
566  // total size 4-bytes for dataStart length
567  // + X number of bytes for dataStart
568  // + 4-bytes for dataEnd length
569  // + X number of bytes for dataEnd
570  uint32_t sz = sizeof (uint32_t)
571  + sizeof (uint32_t)
572  + dataStart
573  + sizeof (uint32_t)
574  + dataEnd;
575 
576  return sz;
577 }
578 
579 uint32_t
580 Buffer::Serialize (uint8_t* buffer, uint32_t maxSize) const
581 {
582  uint32_t* p = reinterpret_cast<uint32_t *> (buffer);
583  uint32_t size = 0;
584 
585  NS_LOG_FUNCTION (this);
586 
587  // Add the zero data length
588  if (size + 4 <= maxSize)
589  {
590  size += 4;
592  }
593  else
594  {
595  return 0;
596  }
597 
598  // Add the length of actual start data
599  uint32_t dataStartLength = m_zeroAreaStart - m_start;
600  if (size + 4 <= maxSize)
601  {
602  size += 4;
603  *p++ = dataStartLength;
604  }
605  else
606  {
607  return 0;
608  }
609 
610  // Add the actual data
611  if (size + ((dataStartLength + 3) & (~3)) <= maxSize)
612  {
613  size += (dataStartLength + 3) & (~3);
614  memcpy (p, m_data->m_data + m_start, dataStartLength);
615  p += (((dataStartLength + 3) & (~3))/4); // Advance p, insuring 4 byte boundary
616  }
617  else
618  {
619  return 0;
620  }
621 
622  // Add the length of the actual end data
623  uint32_t dataEndLength = m_end - m_zeroAreaEnd;
624  if (size + 4 <= maxSize)
625  {
626  size += 4;
627  *p++ = dataEndLength;
628  }
629  else
630  {
631  return 0;
632  }
633 
634  // Add the actual data
635  if (size + ((dataEndLength + 3) & (~3)) <= maxSize)
636  {
637  size += (dataEndLength + 3) & (~3);
638  memcpy (p, m_data->m_data+m_zeroAreaStart,dataEndLength);
639  p += (((dataEndLength + 3) & (~3))/4); // Advance p, insuring 4 byte boundary
640  }
641  else
642  {
643  return 0;
644  }
645 
646  // Serialzed everything successfully
647  return 1;
648 }
649 
650 uint32_t
651 Buffer::Deserialize (const uint8_t *buffer, uint32_t size)
652 {
653  const uint32_t* p = reinterpret_cast<const uint32_t *> (buffer);
654  uint32_t sizeCheck = size-4;
655 
656  NS_ASSERT (sizeCheck >= 4);
657  uint32_t zeroDataLength = *p++;
658  sizeCheck -= 4;
659 
660  // Create zero bytes
661  Initialize (zeroDataLength);
662 
663  // Add start data
664  NS_ASSERT (sizeCheck >= 4);
665  uint32_t dataStartLength = *p++;
666  sizeCheck -= 4;
667  AddAtStart (dataStartLength);
668 
669  NS_ASSERT (sizeCheck >= dataStartLength);
670  Begin ().Write (reinterpret_cast<uint8_t *> (const_cast<uint32_t *> (p)), dataStartLength);
671  p += (((dataStartLength+3)&(~3))/4); // Advance p, insuring 4 byte boundary
672  sizeCheck -= ((dataStartLength+3)&(~3));
673 
674  // Add end data
675  NS_ASSERT (sizeCheck >= 4);
676  uint32_t dataEndLength = *p++;
677  sizeCheck -= 4;
678  AddAtEnd (dataEndLength);
679 
680  NS_ASSERT (sizeCheck >= dataEndLength);
681  Buffer::Iterator tmp = End ();
682  tmp.Prev (dataEndLength);
683  tmp.Write (reinterpret_cast<uint8_t *> (const_cast<uint32_t *> (p)), dataEndLength);
684  p += (((dataEndLength+3)&(~3))/4); // Advance p, insuring 4 byte boundary
685  sizeCheck -= ((dataEndLength+3)&(~3));
686 
687  NS_ASSERT (sizeCheck == 0);
688  // return zero if buffer did not
689  // contain a complete message
690  return (sizeCheck != 0) ? 0 : 1;
691 }
692 
693 int32_t
695 {
696  return m_start;
697 }
698 int32_t
700 {
701  return m_end;
702 }
703 
704 
705 void
707 {
709  Buffer tmp = CreateFullCopy ();
710  *const_cast<Buffer *> (this) = tmp;
712 }
713 
714 
715 uint8_t const*
716 Buffer::PeekData (void) const
717 {
721  return m_data->m_data + m_start;
722 }
723 
724 void
725 Buffer::CopyData (std::ostream *os, uint32_t size) const
726 {
727  if (size > 0)
728  {
729  uint32_t tmpsize = std::min (m_zeroAreaStart-m_start, size);
730  os->write ((const char*)(m_data->m_data + m_start), tmpsize);
731  if (size > tmpsize)
732  {
733  size -= m_zeroAreaStart-m_start;
734  tmpsize = std::min (m_zeroAreaEnd - m_zeroAreaStart, size);
735  uint32_t left = tmpsize;
736  while (left > 0)
737  {
738  uint32_t toWrite = std::min (left, g_zeroes.size);
739  os->write (g_zeroes.buffer, toWrite);
740  left -= toWrite;
741  }
742  if (size > tmpsize)
743  {
744  size -= tmpsize;
745  tmpsize = std::min (m_end - m_zeroAreaEnd, size);
746  os->write ((const char*)(m_data->m_data + m_zeroAreaStart), tmpsize);
747  }
748  }
749  }
750 }
751 
752 uint32_t
753 Buffer::CopyData (uint8_t *buffer, uint32_t size) const
754 {
755  uint32_t originalSize = size;
756  if (size > 0)
757  {
758  uint32_t tmpsize = std::min (m_zeroAreaStart-m_start, size);
759  memcpy (buffer, (const char*)(m_data->m_data + m_start), tmpsize);
760  buffer += tmpsize;
761  size -= tmpsize;
762  if (size > 0)
763  {
764  tmpsize = std::min (m_zeroAreaEnd - m_zeroAreaStart, size);
765  uint32_t left = tmpsize;
766  while (left > 0)
767  {
768  uint32_t toWrite = std::min (left, g_zeroes.size);
769  memcpy (buffer, g_zeroes.buffer, toWrite);
770  left -= toWrite;
771  buffer += toWrite;
772  }
773  size -= tmpsize;
774  if (size > 0)
775  {
776  tmpsize = std::min (m_end - m_zeroAreaEnd, size);
777  memcpy (buffer, (const char*)(m_data->m_data + m_zeroAreaStart), tmpsize);
778  size -= tmpsize;
779  }
780  }
781  }
782  return originalSize - size;
783 }
784 
785 /******************************************************
786  * The buffer iterator below.
787  ******************************************************/
788 
789 
790 uint32_t
792 {
793  NS_ASSERT (m_data == o.m_data);
794  int32_t diff = m_current - o.m_current;
795  if (diff < 0)
796  {
797  return -diff;
798  }
799  else
800  {
801  return diff;
802  }
803 }
804 
805 bool
807 {
808  return m_current == m_dataEnd;
809 }
810 bool
812 {
813  return m_current == m_dataStart;
814 }
815 
816 bool
817 Buffer::Iterator::CheckNoZero (uint32_t start, uint32_t end) const
818 {
819  bool ok = true;
820  for (uint32_t i = start; i < end; i++)
821  {
822  if (!Check (i))
823  {
824  ok = false;
825  }
826  }
827  return ok;
828 }
829 bool
830 Buffer::Iterator::Check (uint32_t i) const
831 {
832  return i >= m_dataStart &&
833  !(i >= m_zeroStart && i < m_zeroEnd) &&
834  i <= m_dataEnd;
835 }
836 
837 
838 void
840 {
841  NS_ASSERT (start.m_data == end.m_data);
842  NS_ASSERT (start.m_current <= end.m_current);
843  NS_ASSERT (start.m_zeroStart == end.m_zeroStart);
844  NS_ASSERT (start.m_zeroEnd == end.m_zeroEnd);
845  NS_ASSERT (m_data != start.m_data);
846  uint32_t size = end.m_current - start.m_current;
847  NS_ASSERT_MSG (CheckNoZero (m_current, m_current + size),
848  GetWriteErrorMessage ());
849  if (start.m_current <= start.m_zeroStart)
850  {
851  uint32_t toCopy = std::min (size, start.m_zeroStart - start.m_current);
852  memcpy (&m_data[m_current], &start.m_data[start.m_current], toCopy);
853  start.m_current += toCopy;
854  m_current += toCopy;
855  size -= toCopy;
856  }
857  if (start.m_current <= start.m_zeroEnd)
858  {
859  uint32_t toCopy = std::min (size, start.m_zeroEnd - start.m_current);
860  memset (&m_data[m_current], 0, toCopy);
861  start.m_current += toCopy;
862  m_current += toCopy;
863  size -= toCopy;
864  }
865  uint32_t toCopy = std::min (size, start.m_dataEnd - start.m_current);
866  uint8_t *from = &start.m_data[start.m_current - (start.m_zeroEnd-start.m_zeroStart)];
867  uint8_t *to = &m_data[m_current];
868  memcpy (to, from, toCopy);
869  m_current += toCopy;
870 }
871 
872 void
874 {
875  WriteU8 (data & 0xff);
876  data >>= 8;
877  WriteU8 (data & 0xff);
878 }
879 void
881 {
882  WriteU8 (data & 0xff);
883  data >>= 8;
884  WriteU8 (data & 0xff);
885  data >>= 8;
886  WriteU8 (data & 0xff);
887  data >>= 8;
888  WriteU8 (data & 0xff);
889 }
890 void
892 {
893  WriteU8 (data & 0xff);
894  data >>= 8;
895  WriteU8 (data & 0xff);
896  data >>= 8;
897  WriteU8 (data & 0xff);
898  data >>= 8;
899  WriteU8 (data & 0xff);
900  data >>= 8;
901  WriteU8 (data & 0xff);
902  data >>= 8;
903  WriteU8 (data & 0xff);
904  data >>= 8;
905  WriteU8 (data & 0xff);
906  data >>= 8;
907  WriteU8 (data & 0xff);
908 }
909 void
911 {
912  WriteU8 ((data >> 0) & 0xff);
913  WriteU8 ((data >> 8) & 0xff);
914 }
915 void
917 {
918  WriteU8 ((data >> 0) & 0xff);
919  WriteU8 ((data >> 8) & 0xff);
920  WriteU8 ((data >> 16) & 0xff);
921  WriteU8 ((data >> 24) & 0xff);
922 }
923 void
925 {
926  WriteU8 ((data >> 0) & 0xff);
927  WriteU8 ((data >> 8) & 0xff);
928  WriteU8 ((data >> 16) & 0xff);
929  WriteU8 ((data >> 24) & 0xff);
930  WriteU8 ((data >> 32) & 0xff);
931  WriteU8 ((data >> 40) & 0xff);
932  WriteU8 ((data >> 48) & 0xff);
933  WriteU8 ((data >> 56) & 0xff);
934 }
935 
936 void
938 {
939  WriteU8 ((data >> 56) & 0xff);
940  WriteU8 ((data >> 48) & 0xff);
941  WriteU8 ((data >> 40) & 0xff);
942  WriteU8 ((data >> 32) & 0xff);
943  WriteU8 ((data >> 24) & 0xff);
944  WriteU8 ((data >> 16) & 0xff);
945  WriteU8 ((data >> 8) & 0xff);
946  WriteU8 ((data >> 0) & 0xff);
947 }
948 void
949 Buffer::Iterator::Write (uint8_t const*buffer, uint32_t size)
950 {
951  NS_ASSERT_MSG (CheckNoZero (m_current, size),
952  GetWriteErrorMessage ());
953  uint8_t *to;
954  if (m_current <= m_zeroStart)
955  {
956  to = &m_data[m_current];
957  }
958  else
959  {
960  to = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
961  }
962  memcpy (to, buffer, size);
963  m_current += size;
964 }
965 
966 uint32_t
968 {
969  uint8_t byte0 = ReadU8 ();
970  uint8_t byte1 = ReadU8 ();
971  uint8_t byte2 = ReadU8 ();
972  uint8_t byte3 = ReadU8 ();
973  uint32_t data = byte3;
974  data <<= 8;
975  data |= byte2;
976  data <<= 8;
977  data |= byte1;
978  data <<= 8;
979  data |= byte0;
980  return data;
981 }
982 uint64_t
984 {
985  uint8_t byte0 = ReadU8 ();
986  uint8_t byte1 = ReadU8 ();
987  uint8_t byte2 = ReadU8 ();
988  uint8_t byte3 = ReadU8 ();
989  uint8_t byte4 = ReadU8 ();
990  uint8_t byte5 = ReadU8 ();
991  uint8_t byte6 = ReadU8 ();
992  uint8_t byte7 = ReadU8 ();
993  uint64_t data = byte7;
994  data <<= 8;
995  data |= byte6;
996  data <<= 8;
997  data |= byte5;
998  data <<= 8;
999  data |= byte4;
1000  data <<= 8;
1001  data |= byte3;
1002  data <<= 8;
1003  data |= byte2;
1004  data <<= 8;
1005  data |= byte1;
1006  data <<= 8;
1007  data |= byte0;
1008 
1009  return data;
1010 }
1011 uint16_t
1013 {
1014  uint16_t retval = 0;
1015  retval |= ReadU8 ();
1016  retval <<= 8;
1017  retval |= ReadU8 ();
1018  return retval;
1019 }
1020 uint32_t
1022 {
1023  uint32_t retval = 0;
1024  retval |= ReadU8 ();
1025  retval <<= 8;
1026  retval |= ReadU8 ();
1027  retval <<= 8;
1028  retval |= ReadU8 ();
1029  retval <<= 8;
1030  retval |= ReadU8 ();
1031  return retval;
1032 }
1033 uint64_t
1035 {
1036  uint64_t retval = 0;
1037  retval |= ReadU8 ();
1038  retval <<= 8;
1039  retval |= ReadU8 ();
1040  retval <<= 8;
1041  retval |= ReadU8 ();
1042  retval <<= 8;
1043  retval |= ReadU8 ();
1044  retval <<= 8;
1045  retval |= ReadU8 ();
1046  retval <<= 8;
1047  retval |= ReadU8 ();
1048  retval <<= 8;
1049  retval |= ReadU8 ();
1050  retval <<= 8;
1051  retval |= ReadU8 ();
1052  return retval;
1053 }
1054 uint16_t
1056 {
1057  uint8_t byte0 = ReadU8 ();
1058  uint8_t byte1 = ReadU8 ();
1059  uint16_t data = byte1;
1060  data <<= 8;
1061  data |= byte0;
1062  return data;
1063 }
1064 uint32_t
1066 {
1067  uint8_t byte0 = ReadU8 ();
1068  uint8_t byte1 = ReadU8 ();
1069  uint8_t byte2 = ReadU8 ();
1070  uint8_t byte3 = ReadU8 ();
1071  uint32_t data = byte3;
1072  data <<= 8;
1073  data |= byte2;
1074  data <<= 8;
1075  data |= byte1;
1076  data <<= 8;
1077  data |= byte0;
1078  return data;
1079 }
1080 uint64_t
1082 {
1083  uint8_t byte0 = ReadU8 ();
1084  uint8_t byte1 = ReadU8 ();
1085  uint8_t byte2 = ReadU8 ();
1086  uint8_t byte3 = ReadU8 ();
1087  uint8_t byte4 = ReadU8 ();
1088  uint8_t byte5 = ReadU8 ();
1089  uint8_t byte6 = ReadU8 ();
1090  uint8_t byte7 = ReadU8 ();
1091  uint64_t data = byte7;
1092  data <<= 8;
1093  data |= byte6;
1094  data <<= 8;
1095  data |= byte5;
1096  data <<= 8;
1097  data |= byte4;
1098  data <<= 8;
1099  data |= byte3;
1100  data <<= 8;
1101  data |= byte2;
1102  data <<= 8;
1103  data |= byte1;
1104  data <<= 8;
1105  data |= byte0;
1106 
1107  return data;
1108 }
1109 void
1110 Buffer::Iterator::Read (uint8_t *buffer, uint32_t size)
1111 {
1112  for (uint32_t i = 0; i < size; i++)
1113  {
1114  buffer[i] = ReadU8 ();
1115  }
1116 }
1117 
1118 uint16_t
1120 {
1121  return CalculateIpChecksum (size, 0);
1122 }
1123 
1124 uint16_t
1125 Buffer::Iterator::CalculateIpChecksum (uint16_t size, uint32_t initialChecksum)
1126 {
1127  /* see RFC 1071 to understand this code. */
1128  uint32_t sum = initialChecksum;
1129 
1130  for (int j = 0; j < size/2; j++)
1131  sum += ReadU16 ();
1132 
1133  if (size & 1)
1134  sum += ReadU8 ();
1135 
1136  while (sum >> 16)
1137  sum = (sum & 0xffff) + (sum >> 16);
1138  return ~sum;
1139 }
1140 
1141 uint32_t
1143 {
1144  return m_dataEnd - m_dataStart;
1145 }
1146 
1147 
1148 std::string
1150 {
1151  std::string str = "You have attempted to read beyond the bounds of the "
1152  "available buffer space. This usually indicates that a "
1153  "Header::Deserialize or Trailer::Deserialize method "
1154  "is trying to read data which was not written by "
1155  "a Header::Serialize or Trailer::Serialize method. "
1156  "In short: check the code of your Serialize and Deserialize "
1157  "methods.";
1158  return str;
1159 }
1160 std::string
1162 {
1163  std::string str;
1164  if (m_current < m_dataStart)
1165  {
1166  str = "You have attempted to write before the start of the available "
1167  "buffer space. This usually indicates that Trailer::GetSerializedSize "
1168  "returned a size which is too small compared to what Trailer::Serialize "
1169  "is actually using.";
1170  }
1171  else if (m_current >= m_dataEnd)
1172  {
1173  str = "You have attempted to write after the end of the available "
1174  "buffer space. This usually indicates that Header::GetSerializedSize "
1175  "returned a size which is too small compared to what Header::Serialize "
1176  "is actually using.";
1177  }
1178  else
1179  {
1180  NS_ASSERT (m_current >= m_zeroStart && m_current < m_zeroEnd);
1181  str = "You have attempted to write inside the payload area of the "
1182  "buffer. This usually indicates that your Serialize method uses more "
1183  "buffer space than what your GetSerialized method returned.";
1184  }
1185  return str;
1186 }
1187 
1188 
1189 } // namespace ns3
1190 
1191